卷土重来的DDoS狂魔：Fodcha僵尸网络再次露出獠牙
<!--kg-card-begin: markdown--><h1 id="">背景</h1>
<p>2022年4月13日，360Netlab首次向社区披露了Fodcha僵尸网络，在我们的文章发表之后，Fodcha遭受到相关部门的打击，其作者迅速做出回应，在样本中留下<code>Netlab pls leave me alone I surrender</code>字样向我们投降。本以为Fodcha会就此淡出江湖，没想到这次投降只是一个<strong>不讲武德的假动作</strong>，Fodcha的作者在诈降之后并没有停下更新的脚步，很快就推出了新版本。</p>
<p>在新版本中，Fodcha的作者重新设计了通信协议，并开始使用xxtea和chacha20算法对敏感资源和网络通信进行加密，以躲避文件&amp;流量层面的检测；同时引入了<strong>OpenNIC 域名</strong>做为主选C2，<strong>ICANN 域名</strong>做为后备C2的双C2方案。这种冗余机制，既能防止C2被接管，又有良好的健壮性，能够维持其主控网络的稳定。</p>
<p>依托于背后团队强大的N-day漏洞整合能力，卷土重来的Focha与之前对比可谓有过之而无不及。在我们的数据视野中，<strong>从规模来看</strong>，Fodcha再次发展成日活Bot节点数超过60K，C2域名绑定40+IP，可以轻松打出超过<strong>1Tbps</strong>流量的大规模僵尸网络；<strong>就活跃程度而言</strong>，Fodcha日均攻击目标100+，累计攻击目标2万多，在10月11日到达了攻击的巅峰，单日“<strong>丧心病狂</strong>”的攻击了<strong>1396个目标</strong>。</p>
<p>在极短的时间内重回巅峰，Fodcha的作者似乎忘了闷声发大财的道理，竟然又开始主动&quot;招惹”我们，在某次扫描的脚本中使用<code>N3t1@bG@Y</code>字样的leetspeak，翻译过来就是&quot;<code>NETLABGAY</code>&quot;，这么明目张胆的黑Netlab，让我们觉得它多多少少有些“皮痒”了。</p>
<p>鉴于Fodcha的规模&amp;活跃程度带来的巨大危险性，以及非常嚣张的挑衅，我们决定撰写本文向社区分享我们的发现，一起打击Fodcha的嚣张气焰，共同维护网络安全。</p>
<h1 id="">时间线</h1>
<p>依托于360Netlab强大的BotMon和DDoSMon系统，我们对Fodcha的样本演变和DDoS攻击指令一直保持着良好跟踪，下面是我们看到的样本演变以及一些重要的DDoS攻击事件。（注：Fodcha样本本身没有特定的标志表明其版本，这是我们内部为了跟踪方便而定的版本号）</p>
<ul>
<li>
<p>2022年1月12日，首次捕获到Fodcha僵尸网络样本。</p>
</li>
<li>
<p>2022年4月13日，首次向外披露Fodcha僵尸网络，包含版本V1，V2。</p>
</li>
<li>
<p>2022年4月19日，捕获版本V2.x，使用<strong>OpenNIC's TLDs风格的C2</strong>（全文简称OpenNIC C2）。</p>
</li>
<li>
<p>2022年4月24日，捕获版本V3，使用xxtea算法加密配置信息，新增<strong>ICANN's TLDs风格的C2</strong>（全文简称ICANN C2），和OpenNIC C2构成冗余机制；新增反沙箱&amp;反调试机制。</p>
</li>
<li>
<p>2022年6月5日，捕获版本V4，使用结构化的配置信息，去除反沙箱&amp;反调试机制。</p>
</li>
<li>
<p>2022年6月7&amp;8日，监控到Fodcha对<strong>某国的某地的健康码机构</strong>进行了DDoS攻击。</p>
</li>
<li>
<p>2022年7月7日，捕获版本V4.x，额外新增一组ICANN C2。</p>
</li>
<li>
<p>2022年9月X日，在协助<strong>某国的某执法机构</strong>固定某公司语音业务被DDoS攻击的证据链过程中，发现攻击背后有Fodcha的影子。</p>
</li>
<li>
<p>2022年9月21日，<strong>某知名云服务商</strong>就一起流量<strong>超过1Tbps</strong>的攻击事件向我们咨询，经过数据的交叉比对，确定攻击方为Fodcha。</p>
</li>
</ul>
<h1 id="">规模推测</h1>
<p>国外合作伙伴的数据表明Fodcha 4月份时全球日活Bot的数量为6W(<a href="__GHOST_URL__/fodcha-a-new-ddos-botnet/">参考我们另一篇文章</a>)，关于Fodcha僵尸网络的目前规模，我们没有确切的数字，但通过对比Fodcha 4月和10月在C2 IP数量上的差异，我们从技术上出发，有个未经验证的猜测：目前Fodcha的日活Bot数量超过6W。</p>
<p>推测过程如下：<br>
僵尸网络的规模与C2 IP的数量存在一个正向关系，最朴素的观点是：“僵尸网络规模越大，所需要的C2基础设施也越多”。在4月份，Fodcha被处置之前，其作者为维持6W的规模，投入了10个C2 IP；随后Fodcha开始了自己的复活之旅，我们观察到一个现象，随着Fodcha的复苏，其C2域名对应的IP在持续增加。时至今日，Fodcha的作者投入了多少C2 IP呢？使用dig命令查询最新的C2域名<code>yellowchinks.dyn</code>的绑定IP，可以看到数量是44。<br>
<a href="__GHOST_URL__/content/images/2022/10/fodcha_c2infras.png"><img src="__GHOST_URL__/content/images/2022/10/fodcha_c2infras.png" class="kg-image"/></a></p>
<p>可以说我们见证了Fodcha的C2 IP一步步从几个增长到今天的40+，可能的解释是作者人傻钱多无脑上资源，但结合其迅猛的传播以及历史上曾看到的万级规模，他们增加C2 IP更可能的原因是因为其僵尸网络规模太大，需要投入更多的IP资源，以使Bot与C2之间在数量上有一个合理比例，达到负载均衡。</p>
<p>综上，我们从C2 IP数量上大幅度的增长，推测目前Fodcha的规模大于4月份，日活Bot数量超过6W。当然<strong>再合理的推测也还是假设</strong>，欢迎有视野的社区伙伴<strong>不吝指正</strong>。</p>
<h1 id="ddos">DDoS统计</h1>
<p>回到C2 IP 44这个数字本身，纵然我们和僵尸网络battle多年见多识广，但这个数字依然让我们感到惊讶。世上没有无缘故的爱，光是这些IP资源，就得花费不少的，Fodcha的作者为什么愿意花这个钱呢？答案是DDoS攻击让他赚到了钱。我们节选了2022年6月29至今的数据，其攻击趋势和目标区域分布如下：</p>
<p><a href="__GHOST_URL__/content/images/2022/10/image--1-.png"><img src="__GHOST_URL__/content/images/2022/10/image.min-1.png" class="kg-image"/></a><br>
可以看出：</p>
<ul>
<li>
<p>无愧于DDoS狂魔的称号，攻击几乎没有停歇，几乎打遍全球，日均攻击事件1K+。</p>
</li>
<li>
<p>中美两国颜色较深，说明两国累计被攻击目标及次数较多，综合考虑到两国在互联网上业务的比重原本就比较大，这里的“看起来多”是一种正常状况。</p>
</li>
</ul>
<p>攻击指令在7天内的时间分布如下所示，可以看出Fodcha发起的DDoS攻击遍及<strong>7 * 24</strong>小时，没有明显的时区性，我们倾向Fodcha是一个商业驱动的僵尸网络。</p>
<p><a href="__GHOST_URL__/content/images/2022/10/fodcha_instimezone.png"><img src="__GHOST_URL__/content/images/2022/10/fodcha_instimezone.png" class="kg-image"/></a></p>
<h1 id="">样本分析</h1>
<p>我们将捕获的样本分成了４个大版本，其中在上一篇blog中已经分析过V1V2，此处就不再赘述了，本文选取最新的V4系列样本为主要分析对象，它们的基本信息如下所示：</p>
<pre><code>MD5: ea7945724837f019507fd613ba3e1da9
ELF 32-bit LSB executable, ARM, version 1, dynamically linked (uses shared libs), stripped
LIB: uclibc
PACKER: None
version: V4

MD5: 899047ddf6f62f07150837aef0c1ebfb
ELF 32-bit LSB executable, ARM, version 1 (SYSV), statically linked, stripped
Lib: uclibc
Packer: None
Version: V4.X
</code></pre>
<p>Fodcha的Bot在被侵入设备运行时，首先会从<code>运行参数</code>，<code>网络的连通性</code>，<code>是否设置“LD_PRELOAD”环境变量</code>，<code>自身是否被调试</code>等方面进行检查，如果不满足要求就直接退出，这些检查可以看成是一种对通过模拟器&amp;沙箱提取IOC的简单对抗。</p>
<p>当满足要求运行要求时，则首先解密出配置信息，在Console上输出<strong>snow slide</strong>，然后就是一些常见的主机行为，如单一实例，进程名伪装，操控watchdog，清空特定端口进程，上报特定进程信息等，我们认为这些主机侧的功能没有太多亮点，因此不再展开分析，下文将着重从解密配置信息，网络通信，DDoS攻击等方面对Fodcha进行剖析。</p>
<h2 id="config">解密配置信息(Config)</h2>
<p>Fodcha在V2.X，V3使用并列的Config组织方式，而在V4,V4.X中则使用结构化的Config组织方式，下图非常清楚的显示了它们的区别。</p>
<p><a href="__GHOST_URL__/content/images/2022/10/fodcha_disconfig.png"><img src="__GHOST_URL__/content/images/2022/10/fodcha_disconfig.png" class="kg-image"/></a></p>
<p>虽然Config的组织方法不一样，但它们的加密方法是一样的，通过下面代码片段引用的常量可知，它们使用的是xxtea算法，密钥为<code>PJbiNbbeasddDfsc</code>。</p>
<p><a href="__GHOST_URL__/content/images/2022/10/fodcha_xxtea.png"><img src="__GHOST_URL__/content/images/2022/10/fodcha_xxtea.png" class="kg-image"/></a></p>
<p>经过逆向，我们编写了以下IDAPYTHON脚本来解密配置信息。</p>
<pre><code># md5: ea7945724837f019507fd613ba3e1da9
# requirement: pip install xxtea-py
# test: ida7.6_python3

import ida_bytes
import xxtea

BufBase=0x1F2B0
ConfBase=0x0001F1A0
key=b&quot;PJbiNbbeasddDfsc&quot;
for i in range(17):
    offset=ida_bytes.get_word(i*16+ConfBase+2)
    leng=ida_bytes.get_word(i*16+ConfBase+4)-offset
    buf=ida_bytes.get_bytes(BufBase+offset,leng)
    print(&quot;index:%d, %s&quot; %(i,xxtea.decrypt(buf,key)))
</code></pre>
<p>解密后的Config信息如下表所示，可以看到index 11还保留着“投降”的彩蛋，另外值得一提的是index 12，它是reporter服务器地址，Fodcha会将一些特定进程的信息上报给它。</p>
<table>
<thead>
<tr>
<th>Index</th>
<th>Value</th>
</tr>
</thead>
<tbody>
<tr>
<td>0</td>
<td>snow slide</td>
</tr>
<tr>
<td>1</td>
<td>/proc/</td>
</tr>
<tr>
<td>2</td>
<td>/stat</td>
</tr>
<tr>
<td>3</td>
<td>/proc/self/exe</td>
</tr>
<tr>
<td>4</td>
<td>/cmdline</td>
</tr>
<tr>
<td>5</td>
<td>/maps</td>
</tr>
<tr>
<td>6</td>
<td>/exe</td>
</tr>
<tr>
<td>7</td>
<td>/lib</td>
</tr>
<tr>
<td>8</td>
<td>/usr/lib</td>
</tr>
<tr>
<td>9</td>
<td>.ri</td>
</tr>
<tr>
<td>10</td>
<td>GET /geoip/?res=10&amp;r HTTP/1.1\r\nHost: 1.1.1.1\r\nConnection: Close\r\n\r\n</td>
</tr>
<tr>
<td>11</td>
<td>Netlab pls leave me alone I surrender</td>
</tr>
<tr>
<td>12</td>
<td>kvsolutions.ru</td>
</tr>
<tr>
<td>13</td>
<td>api.opennicproject.org</td>
</tr>
<tr>
<td>14</td>
<td>watchdog</td>
</tr>
<tr>
<td>15</td>
<td>/dev/</td>
</tr>
<tr>
<td>16</td>
<td>TSource Engine Query</td>
</tr>
</tbody>
</table>
<h2 id="">网络通信</h2>
<p>Fodcha的网络通信在代码层面有一个非常固定的特点：一个永真的While循环，通过switch-case进行各个阶段的处理，因此Fodcha各个版本的网络协议处理函数在IDA中产生的CFG图高度相似，这个特点可以帮助我们对样本进行辨别，对功能快速定位。</p>
<img src="__GHOST_URL__/content/images/2022/10/fodcha_cfg.png"  width="860px" /> 
<p>总的来说，Fodcha的网络通信要经过以下4个步骤：</p>
<ol>
<li>解密C2</li>
<li>DNS查询</li>
<li>建立通信</li>
<li>执行指令</li>
</ol>
<h3 id="0x1c2">0x1: 解密C2</h3>
<p>Fodcha的不同版本支持的C2种类是不一样的，V2.X只有1组OpenNIC C2；V3&amp;V4拥有1组OpenNIC C2，1组ICANN C2；而V4.X则是最多的，1组OpenNIC C2，2组ICANN C2，下面的图非常清楚的显示了它们的区别。</p>
<p><a href="__GHOST_URL__/content/images/2022/10/fodcha_c2_dis.png"><img src="__GHOST_URL__/content/images/2022/10/fodcha_c2_dis.png" class="kg-image"/></a></p>
<p>虽然C2种类&amp;数量不一样，但是它们的处理逻辑如下图所示，几乎是一样的，首先通过C2_GET函数获得一个C2域名，然后通过DNS_QUERY函数获得C2对应的IP，其中C2_GET的第一个参数为C2密文数据，第2个参数为长度，而DNS_QUERY的第2个参数则暗示了C2的类型。</p>
<img src="__GHOST_URL__/content/images/2022/10/FODCHA_c2compose.png"  width="860px" /> 
<p>通过C2_GET可以获得一个有效的C2域名，它内部的实现可以分成2步：</p>
<ul>
<li>首先得解密C2密文数据。</li>
<li>然后将它们构造成一个合法的域名。</li>
</ul>
<h3 id="c2">解密C2密文数据</h3>
<p>C2的密文数据使用了配置信息一样的加密方式，即xxtea，密钥也是<strong>PJbiNbbeasddDfsc</strong>，通过下面简单的IDAPYTHON脚本，即可解密出OpenNic C2数据。</p>
<pre><code>#md5: 899047DDF6F62F07150837AEF0C1EBFB
import xxtea
import ida_bytes
import hexdump
key=b&quot;PJbiNbbeasddDfsc&quot;
buf=ida_bytes.get_bytes(0x0001CA6C,1568)  # Ciphertext of OpenNic C2
plaintext=xxtea.decrypt(buf,key)
print(plaintext)
</code></pre>
<p>解密后的C2数据如下图所示，可以看出C2数据由2部分组成，前面的是domain names，后面是TLDs，它们通过红框中的“<strong>/</strong>”符号分隔。</p>
<img src="__GHOST_URL__/content/images/2022/10/fodcha_c2plaintext.png"  width="860px" /> 
<h3 id="">构造域名</h3>
<p>Fodcha有一个特定的域名构造方法，等效的Python实现如下所示：</p>
<pre><code># md5: 899047ddf6f62f07150837aef0c1ebfb
# requirement: pip install xxtea-py
# test: ida7.6_python3

import xxtea
import ida_bytes

def getcnt(length):
    cnt=1
    while True:
        cnt +=1
        calc=2
        
        for i in range(1,cnt):
            calc+=2+12*i%cnt
                    
        if calc +cnt==length-1:
            return cnt

                        
key=b&quot;PJbiNbbeasddDfsc&quot;
buf=ida_bytes.get_bytes(0x0001CA6C,1568)  # Ciphertext of OpenNic C2
plaintext=xxtea.decrypt(buf,key)

domains,tlds=plaintext.split(b'/')
domainList=domains.split(b',')
tldList=tlds.split(b',')

cnt=getcnt(len(domainList))

print(&quot;------------There're %d C2------------&quot; %cnt)
coff=2
for i in range(0,cnt):
    if i ==0:
        c2Prefix=domainList[i+coff]
    else:
        coff+=12*i %cnt+2
        c2Prefix=domainList[i+coff]
    c2Tld=tldList[(cnt-i-1)*3]
    print(c2Prefix + b'.' + c2Tld)

</code></pre>
<p>将上文得到的C2数据做为输入，最终构造出以下14个OpenNIC C2。</p>
<pre><code>techsupporthelpars.oss
yellowchinks.geek
yellowchinks.dyn
wearelegal.geek
funnyyellowpeople.libre
chinksdogeaters.dyn
blackpeeps.dyn
pepperfan.geek
chinkchink.libre
peepeepoo.libre
respectkkk.geek
bladderfull.indy
tsengtsing.libre
obamalover.pirate
</code></pre>
<p>对ICANN域名体系熟悉的读者，或许会在第一眼就认为我们的解密是错误的，因为ICANN的域名体系并不支持这些TLDs，它们肯定“无法解析”，事实上它们正是OpenNIC体系下的域名，OpenNIC是独立于ICANN的另一套域名体系，它支持下图所示的TLDs，OpenNIC的域名无法通过常见的DNS(如8.8.8.8，101.198.198.198)解析，必须使用指定的NameServer，更多的细节就不再展开，感兴趣的读者自行到其<a href="https://www.opennic.org/"><strong>官方网站</strong></a>了解。</p>
<img src="__GHOST_URL__/content/images/2022/10/fodcha_opennic.png"  width="860px" /> 
<p>用同样的方法，我们可以得到以下4个ICANN C2。</p>
<pre><code>cookiemonsterboob[.]com
forwardchinks[.]com
doodleching[.]com
milfsfors3x[.]com
</code></pre>
<h3 id="0x2dns">0X2: DNS查询</h3>
<p>当成功获得C2域名后，Bot通过函数<strong>DNS_QUERY</strong>进行域名解析，它的第2个参数是一个FLAG，暗示了OpenNIC/ICANN C2的不同处理过程，相应的代码片段如下所示：</p>
<img src="__GHOST_URL__/content/images/2022/10/fodcha_disdns.png"  width="860px" /> 
<p>可以看出对于OpenNIC C2的解析有2个选择：</p>
<ul>
<li>选择1：通过API接口向<strong>api.opennicproject.org</strong>请求，动态的获取nameserver</li>
</ul>
<img src="__GHOST_URL__/content/images/2022/10/fodcha_resolvns.png"  width="860px" /> 
<ul>
<li>选择2：使用下图所示的硬编码nameserver</li>
</ul>
<img src="__GHOST_URL__/content/images/2022/10/fodcha_opennicHard.png"  width="860px" /> 
<p>而对于ICANN C2则只有一个选择，即使用下图中的硬编码nameserver。</p>
<img src="__GHOST_URL__/content/images/2022/10/fodcha_iccanHard.png"  width="860px" /> 
<p>以实际解析 C2“techsupporthelpars.oss”为例，它的解析过程在网络流量中的体现如下所示：</p>
<p><a href="__GHOST_URL__/content/images/2022/10/fodcha_opendnsexample.png"><img src="__GHOST_URL__/content/images/2022/10/fodcha_opendnsexample.png" class="kg-image"/></a></p>
<h3 id="opennicicannc2">为什么使用OpenNIC / ICANN 双C2?</h3>
<p>Fodcha作者构建了一套OpenNIC / ICANN 双C2的冗余结构，他为什么要这么做呢？</p>
<p>从C2基础设施的角度出发，Fodcha被曝光后，其C2被一些服务商加入到了监控列表，进行拦截。例如Quad9DNS（9.9.9.9）就曾发过一个关于Fodcha域名流量spike的Twitter</p>
<img src="__GHOST_URL__/content/images/2022/10/fodcha_quad.png"  width="860px" /> 
<p>在Fodcha被打击之后，其作者在重新选择C2基础设施时，看中了OpenNIC宣传的&quot;DNS Neutrality&quot;特性，通过绕开ICANN的域名体系，从根本上消除C2被监管&amp;接管的可能性，因此Fodcha在V2.X引入OpenNic C2，并将其做为主C2。</p>
<p>与此同时，OpenNIC C2可能存在一些问题，比如OpenNIC的NameServer在某些地区可能无法访问，或者域名解析上存在效率或稳定性的问题。出于健壮性的考虑，Fodcha作者在V3之 后重新加入ICANN C2作为后备C2，与主C2构成冗余结构。</p>
<h3 id="0x3">0x3: 建立通信</h3>
<p>Fodcha Bot通过又下代码片段和C2建立连接，一共有个22个端口。</p>
<img src="__GHOST_URL__/content/images/2022/10/fodcha_establishConn.png"  width="860px" /> 
<p>当成功和C2建立连接后，Bot与C2必须经过3个阶段的交互，才能真正建立通信。</p>
<ul>
<li>阶段1：Bot向C2请求chacha20加密算法的的key&amp;nonce。</li>
<li>阶段2：Bot与C2使用阶段1的key&amp;nonce进行身份确认。</li>
<li>阶段3：Bot将加密后的上线&amp;分组信息发往C2。</li>
</ul>
<p>为了辅助分析，我们在受限的环境内运行了Bot样本，并使用<code>fsdsaD</code>做为分组字串，产生了下图所示的网络流量，下文将详细介绍此流量是如何生成的。</p>
<img src="__GHOST_URL__/content/images/2022/10/fodcha_prapacket.png"  width="860px" /> 
<h3 id="1botc2head7bytesbodyrandom2040bytes">阶段1：Bot ---&gt; C2 ,格式为head(7 bytes) + body( random 20-40 bytes)</h3>
<p>Bot主动向C2发送<strong>netstage=6</strong>的初始化消息，这个消息的格式为head+body，各字段含义如下所示：</p>
<img src="__GHOST_URL__/content/images/2022/10/fodcha_netStageOneb2c.png"  width="860px" /> 
<h4 id="head">head</h4>
<p>head的长度为7 bytes，格式如下所示：</p>
<pre><code>06     		----&gt;netstage,1byte,06 means init
f0 70       ----&gt;tcpip checksum, 2byte, 
00 16		----&gt;length of body, 2 bytes
</code></pre>
<h4 id="checksum">checksum</h4>
<p>head中的checksum使用的是tcp/ip的checksum，它计算对象为整个payload，checksum所在偏移的原始值为&quot;\x00\x00&quot;，checksum的python实现如下所示：</p>
<pre><code class="language-python">def checksum(data):
    s = 0
    n = len(data) % 2
    for i in range(0, len(data)-n, 2):
        s+= ord(data[i]) + (ord(data[i+1]) &lt;&lt; 8)
    if n:
        s+= ord(data[-1])
    while (s &gt;&gt; 16):
        s = (s &amp; 0xFFFF) + (s &gt;&gt; 16)
        s = ~s &amp; 0xffff
    return s

buf=&quot;\x06\x00\x00\x00\x00\x00\x16\x36\x93\x93\xb7\x27\x5c\x9a\x2a\x16\x09\xd8\x13\x32\x01\xd2\x69\x1d\x25\xf3\x42\x00\x32&quot;
print(hex(checksum(buf)))

#hex(checksum(buf))
#0x70f0
</code></pre>
<h4 id="body">body</h4>
<p>body为随机生成的内容，无意义。</p>
<pre><code>00000000  36 93 93 b7 27 5c 9a 2a 16 09 d8 13 32 01 d2 69
00000010  1d 25 f3 42 00 32
</code></pre>
<h3 id="1c2bot2">阶段1：C2---&gt;Bot，共2轮</h3>
<p>当C2收到Bot的<strong>netstage=6</strong>的消息后，就会向BOT发送2轮的数据。</p>
<img src="__GHOST_URL__/content/images/2022/10/fodcha_netStageOne.png"  width="860px" /> 
<ul>
<li>
<p>第一轮，36 bytes , 原信息被xxtea加密，解密后作为chacha20的key，长度为32bytes</p>
<pre><code class="language-python">import hexdump
import xxtea
key=b&quot;PJbiNbbeasddDfsc&quot;
keyBuf=bytes.fromhex(&quot;806d8806cd5460d8996339fbf7bac34ba1e20f792872ba0e05d096ad92a5535e60e55b8d&quot;)
chaKey=xxtea.decrypt(keyBuf,key)
hexdump.hexdump(chaKey)

#chaKey
00000000: E6 7B 1A E3 A4 4B 13 7F  14 15 5E 99 31 F2 5E 3A
00000010: D7 7B AB 0A 4D 5F 00 EF  0C 01 9F 86 94 A4 9D 4B

</code></pre>
</li>
<li>
<p>第二轮，16 bytes，原信息被xxtea加密，解密后作为chacha20的nonce，长度12bytes</p>
<pre><code class="language-python">import hexdump
import xxtea
key=b&quot;PJbiNbbeasddDfsc&quot;
nonBuf=bytes.fromhex(&quot;22c803bb310c5b2512e76a472418f9ee&quot;)
chaNonce=xxtea.decrypt(nonBuf,key)
hexdump.hexdump(chaNonce)

#chaNonce
00000000: 98 79 59 57 A8 BA 7E 13  59 9F 59 6F
</code></pre>
</li>
</ul>
<h3 id="2botc2chacha20">阶段2：Bot---&gt;C2，chacha20加密</h3>
<p>Bot收到chacha20的key和nonce后，就向C2发送<strong>netstage=4</strong>的消息，此次消息使用chacha20加密，key&amp;nonce由上一阶段获得，加密的轮数为1。</p>
<img src="__GHOST_URL__/content/images/2022/10/fodcha_netStageTwob2c.png"  width="860px" /> 
<p>我们可以使用下面的python代码可以解密上面的流量，</p>
<pre><code>from Crypto.Cipher import ChaCha20
cha=ChaCha20.new(key=chaKey,nonce=chaNonce)
cha.seek(64)
tmp=bytes.fromhex('dc23c56943431018b61262481ce5a219da9480930f08714e017edc56bf903d32ac5daeb8314f1bf7e6')
rnd3=cha.decrypt(tmp)
</code></pre>
<p>解密后的流量如下所示，它的格式依然是前文所述的head（7 bytes）+body，其中head的netstage字段的值为04，代表身份认证。</p>
<img src="__GHOST_URL__/content/images/2022/10/fodcha_netplainb2c.png"  width="860px" /> 
<h3 id="2c2botchacha20">阶段2：C2---&gt;Bot，chacha20加密</h3>
<p>C2在收到Bot的身份认证消息后，也向Bot的数据发送<strong>netstage=4</strong>的消息，同样使用chacha20加密，且key,nonce,轮数和Bot使用的是一样的。</p>
<img src="__GHOST_URL__/content/images/2022/10/fodcha_netStageTwoc2b.png"  width="860px" /> 
<p>使用和Bot相同的代码解密流量，可以看出它的格式也是head+body，netstage的值也为04。</p>
<img src="__GHOST_URL__/content/images/2022/10/fodcha_netplainc2b.png"  width="860px" /> 
<p>在Bot和C2互发<strong>netstage=4</strong>的消息之后，代表阶段1的chacha20 key&amp;nonce被双方认可，彼此的身份认证完成，Bot进入下一阶段准备上线。</p>
<h3 id="3botc22chacha">阶段3：Bot---&gt;C2，共2轮，chacha加密</h3>
<p>Bot向C2发送<strong>netstage=5</strong>的消息，表示准备上线，接着再自己的分组信息上报给C2，这2轮消息也使用chacha20加密。</p>
<ul>
<li>
<p>第一轮<br>
<img src="__GHOST_URL__/content/images/2022/10/fodcha_netStageThrReg.png"  width="860px" /></p>
</li>
<li>
<p>第二轮</p>
 <img src="__GHOST_URL__/content/images/2022/10/fodcha_netStageThrGroup.png"  width="860px" /> 
</li>
</ul>
<p>上述2轮的数据解密后如下所示，可以看出分组的内容正是预设的&quot;<code>fsdsaD</code>&quot;，这代表我们的分析是正确的，至此Bot成功上线，开始等待执行C2下发的指令。</p>
<img src="__GHOST_URL__/content/images/2022/10/fodcha_netplainb2cReg.png"  width="860px" /> 
<h3 id="0x4">0x4:执行指令</h3>
<p>Bot成功上线后，支持的netstage编号，如下所图所示，其中最重要的就是<strong>netstage=1</strong>代表DDoS任务，Fodcha复用了大量Mirai的攻击代码，一共支持17种攻击方法。</p>
<img src="__GHOST_URL__/content/images/2022/10/fodcha_afterreg.png"  width="860px" /> 
<p>以下图的DDos_Task流量（netstage=01）为例：</p>
<img src="__GHOST_URL__/content/images/2022/10/fodcha_taskddos.png"  width="860px" /> 
<p>攻击指令依然采用chacha20加密，解密后的指令如下所示，相信熟悉Mirai的读者看到此处肯定会心一笑。</p>
<pre><code>00000000: 00 00 00 3C 07 01 xx 14  93 01 20 02 00 00 02 01
00000010: BB 01 00 02 00 01
</code></pre>
<p>上述攻击指令的格式和解析方式如下表所示：</p>
<table>
<thead>
<tr>
<th>offset</th>
<th>len (bytes)</th>
<th>value</th>
<th>meaning</th>
</tr>
</thead>
<tbody>
<tr>
<td>0x00</td>
<td>4</td>
<td>00 00 00 3c</td>
<td>Duration</td>
</tr>
<tr>
<td>0x04</td>
<td>1</td>
<td>07</td>
<td>Attack Vector，07</td>
</tr>
<tr>
<td>0x05</td>
<td>1</td>
<td>1</td>
<td>Attack Target Cnt</td>
</tr>
<tr>
<td>0x06</td>
<td>4</td>
<td>xx 14  93 01</td>
<td>Attack Target，xx.20.147.1</td>
</tr>
<tr>
<td>0x0a</td>
<td>1</td>
<td>20</td>
<td>Netmask</td>
</tr>
<tr>
<td>0x0b</td>
<td>1</td>
<td>02</td>
<td>Option Cnt</td>
</tr>
<tr>
<td>0x0c</td>
<td>5</td>
<td>00 00 02 01 bb</td>
<td>OptionId 0，len 2, value 0x01bb ---&gt; (port 443)</td>
</tr>
<tr>
<td>0x11</td>
<td>5</td>
<td>01 00 02 00 01</td>
<td>OptionId 1, len 2, value 0x0001---&gt; (payload len 1 byte)</td>
</tr>
</tbody>
</table>
<p>当Bot接收到上述指令，就会使用payload为1字节的tcp报文对目标xx.20.147.1:443进行DDoS攻击，这和实际抓包的流量是能对应上的。</p>
<p><a href="__GHOST_URL__/content/images/2022/10/fodcha_ddospacket.png"><img src="__GHOST_URL__/content/images/2022/10/fodcha_ddospacket.png" class="kg-image"/></a></p>
<h1 id="">花絮</h1>
<h3 id="0x01">0x01: 种族歧视</h3>
<p>从某些OpenNIC C2的构词上来说，Fodcha的作者似乎对黄种人，黑人有比较大的敌意。</p>
<pre><code>yellowchinks.geek
wearelegal.geek
funnyyellowpeople.libre
chinksdogeaters.dyn
blackpeeps.dyn
bladderfull.indy

wehateyellow
</code></pre>
<h3 id="0x02">0x02: 攻击即勒索</h3>
<p>Fodcha曾在其下发的UDP攻击指令中，附带以下字串：</p>
<pre><code>send 10 xmr to 49UnJhpvRRxDXJHYczoUEiK3EKCQZorZWaV6HD7axKGQd5xpUQeNp7Xg9RATFpL4u8dzPfAnuMYqs2Kch1soaf5B5mdfJ1b or we will shutdown your business
</code></pre>
<p>Bot打出的攻击流量如下所示，该钱包地址似乎是非法的，没能给我们更多的线索，但从这一行为出发，或许Fodcha背后的运营者正在尝试攻击即勒索这种商业模式。<br>
<a href="__GHOST_URL__/content/images/2022/10/fodcha_ddosransom.png"><img src="__GHOST_URL__/content/images/2022/10/fodcha_ddosransom.png" class="kg-image"/></a></p>
<h1 id="">联系我们</h1>
<p>感兴趣的读者，可以在 <a href="https://twitter.com/360Netlab">twitter</a> 或者通过邮件netlab[at]360.cn联系我们。</p>
<h1 id="">解决方案</h1>
<p>基于Netlab多年研究工作孵化的360全系列<a href="https://sdns.360.net/">DNS安全产品</a>均已支持文中远控服务器的拦截和检测，同时内置多种算法可有效发现和拦截各种未知威胁，建议企业客户接入360 DNS安全SaaS平台或部署本地360DNS安全产品，及时防范此类新型威胁，避免企业资产失陷。联系人: <a href="mailto:wangkun-bd@360.cn">wangkun-bd@360.cn</a></p>
<h1 id="ioc">IoC</h1>
<h3 id="c2">C2</h3>
<pre><code>yellowchinks.geek
yellowchinks.dyn
wearelegal.geek
tsengtsing.libre
techsupporthelpars.oss
respectkkk.geek
pepperfan.geek
peepeepoo.libre
obamalover.pirate
milfsfors3x[.]com
funnyyellowpeople.libre
fridgexperts[.]cc
forwardchinks[.]com
folded[.]in
doodleching[.]com
cookiemonsterboob[.]com
chinksdogeaters.dyn
chinkchink.libre
bladderfull.indy
blackpeeps.dyn
91.206.93.243
91.149.232.129
91.149.232.128
91.149.222.133
91.149.222.132
67.207.84.82
54.37.243.73
51.89.239.122
51.89.238.199
51.89.176.228
51.89.171.33
51.161.98.214
46.17.47.212
46.17.41.79
45.88.221.143
45.61.139.116
45.41.240.145
45.147.200.168
45.140.169.122
45.135.135.33
3.70.127.241
3.65.206.229
3.122.255.225
3.121.234.237
3.0.58.143
23.183.83.171
207.154.206.0
207.154.199.110
195.211.96.142
195.133.53.157
195.133.53.148
194.87.197.3
194.53.108.94
194.53.108.159
194.195.117.167
194.156.224.102
194.147.87.242
194.147.86.22
193.233.253.93
193.233.253.220
193.203.12.157
193.203.12.156
193.203.12.155
193.203.12.154
193.203.12.151
193.203.12.123
193.124.24.42
192.46.225.170
185.45.192.96
185.45.192.227
185.45.192.212
185.45.192.124
185.45.192.103
185.198.57.95
185.198.57.105
185.183.98.205
185.183.96.7
185.143.221.129
185.143.220.75
185.141.27.238
185.141.27.234
185.117.75.45
185.117.75.34
185.117.75.119
185.117.73.52
185.117.73.147
185.117.73.115
185.117.73.109
18.185.188.32
18.136.209.2
178.62.204.81
176.97.210.176
172.105.59.204
172.105.55.131
172.104.108.53
170.187.187.99
167.114.124.77
165.227.19.36
159.65.158.148
159.223.39.133
157.230.15.82
15.204.18.232
15.204.18.203
15.204.128.25
149.56.42.246
139.99.166.217
139.99.153.49
139.99.142.215
139.162.69.4
138.68.10.149
137.74.65.164
13.229.98.186
107.181.160.173
107.181.160.172
</code></pre>
<h3 id="reporter">Reporter</h3>
<pre><code>kvsolutions[.]ru
icarlyfanss[.]com
</code></pre>
<h3 id="samples">Samples</h3>
<pre><code>ea7945724837f019507fd613ba3e1da9
899047ddf6f62f07150837aef0c1ebfb
0f781868d4b9203569357b2dbc46ef10
</code></pre>
<!--kg-card-end: markdown-->
背景


2022年4月13日，360Netlab首次向社区披露了Fodcha僵尸网络，在我们的文章发表之后，Fodcha遭受到相关部门的打击，其作者迅速做出回应，在样本中留下Netlab pls leave me alone I surrender字样向我们投降。本以为Fodcha会就此淡出江湖，没想到这次投降只是一个不讲武德的假动作，Fodcha的作者在诈降之后并没有停下更新的脚步，很快就推出了新版本。


在新版本中，Fodcha的作者重新设计了通信协议，并开始使用xxtea和chacha20算法对敏感资源和网络通信进行加密，以躲避文件&流量层面的检测；同时引入了OpenNIC 域名做为主选C2，ICANN 域名做为后备C2的双C2方案。这种冗余机制，既能防止C2被接管，又有良好的健壮性，能够维持其主控网络的稳定。


依托于背后团队强大的N-day漏洞整合能力，卷土重来的Focha与之前对比可谓有过之而无不及。在我们的数据视野中，从规模来看，Fodcha再次发展成日活Bot节点数超过60K，C2域名绑定40+IP，可以轻松打出超过1Tbps流量的大规模僵尸网络；就活跃程度而言，Fodcha日均攻击目标100+，累计攻击目标2万多，在10月11日到达了攻击的巅峰，单日“丧心病狂”的攻击了1396个目标。


在极短的时间内重回巅峰，Fodcha的作者似乎忘了闷声发大财的道理，竟然又开始主动"招惹”我们，在某次扫描的脚本中使用N3t1@bG@Y字样的leetspeak，翻译过来就是"NETLABGAY"，这么明目张胆的黑Netlab，让我们觉得它多多少少有些“皮痒”了。


鉴于Fodcha的规模&活跃程度带来的巨大危险性，以及非常嚣张的挑衅，我们决定撰写本文向社区分享我们的发现，一起打击Fodcha的嚣张气焰，共同维护网络安全。



时间线


依托于360Netlab强大的BotMon和DDoSMon系统，我们对Fodcha的样本演变和DDoS攻击指令一直保持着良好跟踪，下面是我们看到的样本演变以及一些重要的DDoS攻击事件。（注：Fodcha样本本身没有特定的标志表明其版本，这是我们内部为了跟踪方便而定的版本号）


 * 
   
   
   2022年1月12日，首次捕获到Fodcha僵尸网络样本。
   

 * 
   
   
   2022年4月13日，首次向外披露Fodcha僵尸网络，包含版本V1，V2。
   

 * 
   
   
   2022年4月19日，捕获版本V2.x，使用OpenNIC's TLDs风格的C2（全文简称OpenNIC C2）。
   

 * 
   
   
   2022年4月24日，捕获版本V3，使用xxtea算法加密配置信息，新增ICANN's TLDs风格的C2（全文简称ICANN C2），和OpenNIC C2构成冗余机制；新增反沙箱&反调试机制。
   

 * 
   
   
   2022年6月5日，捕获版本V4，使用结构化的配置信息，去除反沙箱&反调试机制。
   

 * 
   
   
   2022年6月7&8日，监控到Fodcha对某国的某地的健康码机构进行了DDoS攻击。
   

 * 
   
   
   2022年7月7日，捕获版本V4.x，额外新增一组ICANN C2。
   

 * 
   
   
   2022年9月X日，在协助某国的某执法机构固定某公司语音业务被DDoS攻击的证据链过程中，发现攻击背后有Fodcha的影子。
   

 * 
   
   
   2022年9月21日，某知名云服务商就一起流量超过1Tbps的攻击事件向我们咨询，经过数据的交叉比对，确定攻击方为Fodcha。
   



规模推测


国外合作伙伴的数据表明Fodcha 4月份时全球日活Bot的数量为6W(参考我们另一篇文章)，关于Fodcha僵尸网络的目前规模，我们没有确切的数字，但通过对比Fodcha 4月和10月在C2 IP数量上的差异，我们从技术上出发，有个未经验证的猜测：目前Fodcha的日活Bot数量超过6W。


推测过程如下：

僵尸网络的规模与C2 IP的数量存在一个正向关系，最朴素的观点是：“僵尸网络规模越大，所需要的C2基础设施也越多”。在4月份，Fodcha被处置之前，其作者为维持6W的规模，投入了10个C2 IP；随后Fodcha开始了自己的复活之旅，我们观察到一个现象，随着Fodcha的复苏，其C2域名对应的IP在持续增加。时至今日，Fodcha的作者投入了多少C2 IP呢？使用dig命令查询最新的C2域名yellowchinks.dyn的绑定IP，可以看到数量是44。




可以说我们见证了Fodcha的C2 IP一步步从几个增长到今天的40+，可能的解释是作者人傻钱多无脑上资源，但结合其迅猛的传播以及历史上曾看到的万级规模，他们增加C2 IP更可能的原因是因为其僵尸网络规模太大，需要投入更多的IP资源，以使Bot与C2之间在数量上有一个合理比例，达到负载均衡。


综上，我们从C2 IP数量上大幅度的增长，推测目前Fodcha的规模大于4月份，日活Bot数量超过6W。当然再合理的推测也还是假设，欢迎有视野的社区伙伴不吝指正。



DDoS统计


回到C2 IP 44这个数字本身，纵然我们和僵尸网络battle多年见多识广，但这个数字依然让我们感到惊讶。世上没有无缘故的爱，光是这些IP资源，就得花费不少的，Fodcha的作者为什么愿意花这个钱呢？答案是DDoS攻击让他赚到了钱。我们节选了2022年6月29至今的数据，其攻击趋势和目标区域分布如下：




可以看出：


 * 
   
   
   无愧于DDoS狂魔的称号，攻击几乎没有停歇，几乎打遍全球，日均攻击事件1K+。
   

 * 
   
   
   中美两国颜色较深，说明两国累计被攻击目标及次数较多，综合考虑到两国在互联网上业务的比重原本就比较大，这里的“看起来多”是一种正常状况。
   


攻击指令在7天内的时间分布如下所示，可以看出Fodcha发起的DDoS攻击遍及7 * 24小时，没有明显的时区性，我们倾向Fodcha是一个商业驱动的僵尸网络。






样本分析


我们将捕获的样本分成了４个大版本，其中在上一篇blog中已经分析过V1V2，此处就不再赘述了，本文选取最新的V4系列样本为主要分析对象，它们的基本信息如下所示：


MD5: ea7945724837f019507fd613ba3e1da9
ELF 32-bit LSB executable, ARM, version 1, dynamically linked (uses shared libs), stripped
LIB: uclibc
PACKER: None
version: V4

MD5: 899047ddf6f62f07150837aef0c1ebfb
ELF 32-bit LSB executable, ARM, version 1 (SYSV), statically linked, stripped
Lib: uclibc
Packer: None
Version: V4.X



Fodcha的Bot在被侵入设备运行时，首先会从运行参数，网络的连通性，是否设置“LD_PRELOAD”环境变量，自身是否被调试等方面进行检查，如果不满足要求就直接退出，这些检查可以看成是一种对通过模拟器&沙箱提取IOC的简单对抗。


当满足要求运行要求时，则首先解密出配置信息，在Console上输出snow slide，然后就是一些常见的主机行为，如单一实例，进程名伪装，操控watchdog，清空特定端口进程，上报特定进程信息等，我们认为这些主机侧的功能没有太多亮点，因此不再展开分析，下文将着重从解密配置信息，网络通信，DDoS攻击等方面对Fodcha进行剖析。



解密配置信息(Config)


Fodcha在V2.X，V3使用并列的Config组织方式，而在V4,V4.X中则使用结构化的Config组织方式，下图非常清楚的显示了它们的区别。





虽然Config的组织方法不一样，但它们的加密方法是一样的，通过下面代码片段引用的常量可知，它们使用的是xxtea算法，密钥为PJbiNbbeasddDfsc。





经过逆向，我们编写了以下IDAPYTHON脚本来解密配置信息。


# md5: ea7945724837f019507fd613ba3e1da9
# requirement: pip install xxtea-py
# test: ida7.6_python3

import ida_bytes
import xxtea

BufBase=0x1F2B0
ConfBase=0x0001F1A0
key=b"PJbiNbbeasddDfsc"
for i in range(17):
    offset=ida_bytes.get_word(i*16+ConfBase+2)
    leng=ida_bytes.get_word(i*16+ConfBase+4)-offset
    buf=ida_bytes.get_bytes(BufBase+offset,leng)
    print("index:%d, %s" %(i,xxtea.decrypt(buf,key)))



解密后的Config信息如下表所示，可以看到index 11还保留着“投降”的彩蛋，另外值得一提的是index 12，它是reporter服务器地址，Fodcha会将一些特定进程的信息上报给它。





Index
Value




0
snow slide


1
/proc/


2
/stat


3
/proc/self/exe


4
/cmdline


5
/maps


6
/exe


7
/lib


8
/usr/lib


9
.ri


10
GET /geoip/?res=10&r HTTP/1.1\r\nHost: 1.1.1.1\r\nConnection: Close\r\n\r\n


11
Netlab pls leave me alone I surrender


12
kvsolutions.ru


13
api.opennicproject.org


14
watchdog


15
/dev/


16
TSource Engine Query






网络通信


Fodcha的网络通信在代码层面有一个非常固定的特点：一个永真的While循环，通过switch-case进行各个阶段的处理，因此Fodcha各个版本的网络协议处理函数在IDA中产生的CFG图高度相似，这个特点可以帮助我们对样本进行辨别，对功能快速定位。



总的来说，Fodcha的网络通信要经过以下4个步骤：


 1. 解密C2
 2. DNS查询
 3. 建立通信
 4. 执行指令



0x1: 解密C2


Fodcha的不同版本支持的C2种类是不一样的，V2.X只有1组OpenNIC C2；V3&V4拥有1组OpenNIC C2，1组ICANN C2；而V4.X则是最多的，1组OpenNIC C2，2组ICANN C2，下面的图非常清楚的显示了它们的区别。





虽然C2种类&数量不一样，但是它们的处理逻辑如下图所示，几乎是一样的，首先通过C2_GET函数获得一个C2域名，然后通过DNS_QUERY函数获得C2对应的IP，其中C2_GET的第一个参数为C2密文数据，第2个参数为长度，而DNS_QUERY的第2个参数则暗示了C2的类型。



通过C2_GET可以获得一个有效的C2域名，它内部的实现可以分成2步：


 * 首先得解密C2密文数据。
 * 然后将它们构造成一个合法的域名。



解密C2密文数据


C2的密文数据使用了配置信息一样的加密方式，即xxtea，密钥也是PJbiNbbeasddDfsc，通过下面简单的IDAPYTHON脚本，即可解密出OpenNic C2数据。


#md5: 899047DDF6F62F07150837AEF0C1EBFB
import xxtea
import ida_bytes
import hexdump
key=b"PJbiNbbeasddDfsc"
buf=ida_bytes.get_bytes(0x0001CA6C,1568)  # Ciphertext of OpenNic C2
plaintext=xxtea.decrypt(buf,key)
print(plaintext)



解密后的C2数据如下图所示，可以看出C2数据由2部分组成，前面的是domain names，后面是TLDs，它们通过红框中的“/”符号分隔。




构造域名


Fodcha有一个特定的域名构造方法，等效的Python实现如下所示：


# md5: 899047ddf6f62f07150837aef0c1ebfb
# requirement: pip install xxtea-py
# test: ida7.6_python3

import xxtea
import ida_bytes

def getcnt(length):
    cnt=1
    while True:
        cnt +=1
        calc=2
        
        for i in range(1,cnt):
            calc+=2+12*i%cnt
                    
        if calc +cnt==length-1:
            return cnt

                        
key=b"PJbiNbbeasddDfsc"
buf=ida_bytes.get_bytes(0x0001CA6C,1568)  # Ciphertext of OpenNic C2
plaintext=xxtea.decrypt(buf,key)

domains,tlds=plaintext.split(b'/')
domainList=domains.split(b',')
tldList=tlds.split(b',')

cnt=getcnt(len(domainList))

print("------------There're %d C2------------" %cnt)
coff=2
for i in range(0,cnt):
    if i ==0:
        c2Prefix=domainList[i+coff]
    else:
        coff+=12*i %cnt+2
        c2Prefix=domainList[i+coff]
    c2Tld=tldList[(cnt-i-1)*3]
    print(c2Prefix + b'.' + c2Tld)




将上文得到的C2数据做为输入，最终构造出以下14个OpenNIC C2。


techsupporthelpars.oss
yellowchinks.geek
yellowchinks.dyn
wearelegal.geek
funnyyellowpeople.libre
chinksdogeaters.dyn
blackpeeps.dyn
pepperfan.geek
chinkchink.libre
peepeepoo.libre
respectkkk.geek
bladderfull.indy
tsengtsing.libre
obamalover.pirate



对ICANN域名体系熟悉的读者，或许会在第一眼就认为我们的解密是错误的，因为ICANN的域名体系并不支持这些TLDs，它们肯定“无法解析”，事实上它们正是OpenNIC体系下的域名，OpenNIC是独立于ICANN的另一套域名体系，它支持下图所示的TLDs，OpenNIC的域名无法通过常见的DNS(如8.8.8.8，101.198.198.198)解析，必须使用指定的NameServer，更多的细节就不再展开，感兴趣的读者自行到其官方网站了解。



用同样的方法，我们可以得到以下4个ICANN C2。


cookiemonsterboob[.]com
forwardchinks[.]com
doodleching[.]com
milfsfors3x[.]com




0X2: DNS查询


当成功获得C2域名后，Bot通过函数DNS_QUERY进行域名解析，它的第2个参数是一个FLAG，暗示了OpenNIC/ICANN C2的不同处理过程，相应的代码片段如下所示：



可以看出对于OpenNIC C2的解析有2个选择：


 * 选择1：通过API接口向api.opennicproject.org请求，动态的获取nameserver



 * 选择2：使用下图所示的硬编码nameserver



而对于ICANN C2则只有一个选择，即使用下图中的硬编码nameserver。



以实际解析 C2“techsupporthelpars.oss”为例，它的解析过程在网络流量中的体现如下所示：






为什么使用OpenNIC / ICANN 双C2?


Fodcha作者构建了一套OpenNIC / ICANN 双C2的冗余结构，他为什么要这么做呢？


从C2基础设施的角度出发，Fodcha被曝光后，其C2被一些服务商加入到了监控列表，进行拦截。例如Quad9DNS（9.9.9.9）就曾发过一个关于Fodcha域名流量spike的Twitter



在Fodcha被打击之后，其作者在重新选择C2基础设施时，看中了OpenNIC宣传的"DNS Neutrality"特性，通过绕开ICANN的域名体系，从根本上消除C2被监管&接管的可能性，因此Fodcha在V2.X引入OpenNic C2，并将其做为主C2。


与此同时，OpenNIC C2可能存在一些问题，比如OpenNIC的NameServer在某些地区可能无法访问，或者域名解析上存在效率或稳定性的问题。出于健壮性的考虑，Fodcha作者在V3之 后重新加入ICANN C2作为后备C2，与主C2构成冗余结构。



0x3: 建立通信


Fodcha Bot通过又下代码片段和C2建立连接，一共有个22个端口。



当成功和C2建立连接后，Bot与C2必须经过3个阶段的交互，才能真正建立通信。


 * 阶段1：Bot向C2请求chacha20加密算法的的key&nonce。
 * 阶段2：Bot与C2使用阶段1的key&nonce进行身份确认。
 * 阶段3：Bot将加密后的上线&分组信息发往C2。


为了辅助分析，我们在受限的环境内运行了Bot样本，并使用fsdsaD做为分组字串，产生了下图所示的网络流量，下文将详细介绍此流量是如何生成的。




阶段1：Bot ---> C2 ,格式为head(7 bytes) + body( random 20-40 bytes)


Bot主动向C2发送netstage=6的初始化消息，这个消息的格式为head+body，各字段含义如下所示：



head


head的长度为7 bytes，格式如下所示：


06     		---->netstage,1byte,06 means init
f0 70       ---->tcpip checksum, 2byte, 
00 16		---->length of body, 2 bytes



checksum


head中的checksum使用的是tcp/ip的checksum，它计算对象为整个payload，checksum所在偏移的原始值为"\x00\x00"，checksum的python实现如下所示：


def checksum(data):
    s = 0
    n = len(data) % 2
    for i in range(0, len(data)-n, 2):
        s+= ord(data[i]) + (ord(data[i+1]) << 8)
    if n:
        s+= ord(data[-1])
    while (s >> 16):
        s = (s & 0xFFFF) + (s >> 16)
        s = ~s & 0xffff
    return s

buf="\x06\x00\x00\x00\x00\x00\x16\x36\x93\x93\xb7\x27\x5c\x9a\x2a\x16\x09\xd8\x13\x32\x01\xd2\x69\x1d\x25\xf3\x42\x00\x32"
print(hex(checksum(buf)))

#hex(checksum(buf))
#0x70f0



body


body为随机生成的内容，无意义。


00000000  36 93 93 b7 27 5c 9a 2a 16 09 d8 13 32 01 d2 69
00000010  1d 25 f3 42 00 32




阶段1：C2--->Bot，共2轮


当C2收到Bot的netstage=6的消息后，就会向BOT发送2轮的数据。



 * 
   
   
   第一轮，36 bytes , 原信息被xxtea加密，解密后作为chacha20的key，长度为32bytes
   
   
   import hexdump
   import xxtea
   key=b"PJbiNbbeasddDfsc"
   keyBuf=bytes.fromhex("806d8806cd5460d8996339fbf7bac34ba1e20f792872ba0e05d096ad92a5535e60e55b8d")
   chaKey=xxtea.decrypt(keyBuf,key)
   hexdump.hexdump(chaKey)
   
   #chaKey
   00000000: E6 7B 1A E3 A4 4B 13 7F  14 15 5E 99 31 F2 5E 3A
   00000010: D7 7B AB 0A 4D 5F 00 EF  0C 01 9F 86 94 A4 9D 4B
   
   
   

 * 
   
   
   第二轮，16 bytes，原信息被xxtea加密，解密后作为chacha20的nonce，长度12bytes
   
   
   import hexdump
   import xxtea
   key=b"PJbiNbbeasddDfsc"
   nonBuf=bytes.fromhex("22c803bb310c5b2512e76a472418f9ee")
   chaNonce=xxtea.decrypt(nonBuf,key)
   hexdump.hexdump(chaNonce)
   
   #chaNonce
   00000000: 98 79 59 57 A8 BA 7E 13  59 9F 59 6F
   
   



阶段2：Bot--->C2，chacha20加密


Bot收到chacha20的key和nonce后，就向C2发送netstage=4的消息，此次消息使用chacha20加密，key&nonce由上一阶段获得，加密的轮数为1。



我们可以使用下面的python代码可以解密上面的流量，


from Crypto.Cipher import ChaCha20
cha=ChaCha20.new(key=chaKey,nonce=chaNonce)
cha.seek(64)
tmp=bytes.fromhex('dc23c56943431018b61262481ce5a219da9480930f08714e017edc56bf903d32ac5daeb8314f1bf7e6')
rnd3=cha.decrypt(tmp)



解密后的流量如下所示，它的格式依然是前文所述的head（7 bytes）+body，其中head的netstage字段的值为04，代表身份认证。




阶段2：C2--->Bot，chacha20加密


C2在收到Bot的身份认证消息后，也向Bot的数据发送netstage=4的消息，同样使用chacha20加密，且key,nonce,轮数和Bot使用的是一样的。



使用和Bot相同的代码解密流量，可以看出它的格式也是head+body，netstage的值也为04。



在Bot和C2互发netstage=4的消息之后，代表阶段1的chacha20 key&nonce被双方认可，彼此的身份认证完成，Bot进入下一阶段准备上线。



阶段3：Bot--->C2，共2轮，chacha加密


Bot向C2发送netstage=5的消息，表示准备上线，接着再自己的分组信息上报给C2，这2轮消息也使用chacha20加密。


 * 
   
   
   第一轮
   
   
   

 * 
   
   
   第二轮
   
   


上述2轮的数据解密后如下所示，可以看出分组的内容正是预设的"fsdsaD"，这代表我们的分析是正确的，至此Bot成功上线，开始等待执行C2下发的指令。




0x4:执行指令


Bot成功上线后，支持的netstage编号，如下所图所示，其中最重要的就是netstage=1代表DDoS任务，Fodcha复用了大量Mirai的攻击代码，一共支持17种攻击方法。



以下图的DDos_Task流量（netstage=01）为例：



攻击指令依然采用chacha20加密，解密后的指令如下所示，相信熟悉Mirai的读者看到此处肯定会心一笑。


00000000: 00 00 00 3C 07 01 xx 14  93 01 20 02 00 00 02 01
00000010: BB 01 00 02 00 01



上述攻击指令的格式和解析方式如下表所示：





offset
len (bytes)
value
meaning




0x00
4
00 00 00 3c
Duration


0x04
1
07
Attack Vector，07


0x05
1
1
Attack Target Cnt


0x06
4
xx 14 93 01
Attack Target，xx.20.147.1


0x0a
1
20
Netmask


0x0b
1
02
Option Cnt


0x0c
5
00 00 02 01 bb
OptionId 0，len 2, value 0x01bb ---> (port 443)


0x11
5
01 00 02 00 01
OptionId 1, len 2, value 0x0001---> (payload len 1 byte)





当Bot接收到上述指令，就会使用payload为1字节的tcp报文对目标xx.20.147.1:443进行DDoS攻击，这和实际抓包的流量是能对应上的。






花絮



0x01: 种族歧视


从某些OpenNIC C2的构词上来说，Fodcha的作者似乎对黄种人，黑人有比较大的敌意。


yellowchinks.geek
wearelegal.geek
funnyyellowpeople.libre
chinksdogeaters.dyn
blackpeeps.dyn
bladderfull.indy

wehateyellow




0x02: 攻击即勒索


Fodcha曾在其下发的UDP攻击指令中，附带以下字串：


send 10 xmr to 49UnJhpvRRxDXJHYczoUEiK3EKCQZorZWaV6HD7axKGQd5xpUQeNp7Xg9RATFpL4u8dzPfAnuMYqs2Kch1soaf5B5mdfJ1b or we will shutdown your business



Bot打出的攻击流量如下所示，该钱包地址似乎是非法的，没能给我们更多的线索，但从这一行为出发，或许Fodcha背后的运营者正在尝试攻击即勒索这种商业模式。





联系我们


感兴趣的读者，可以在 twitter 或者通过邮件netlab[at]360.cn联系我们。



解决方案


基于Netlab多年研究工作孵化的360全系列DNS安全产品均已支持文中远控服务器的拦截和检测，同时内置多种算法可有效发现和拦截各种未知威胁，建议企业客户接入360 DNS安全SaaS平台或部署本地360DNS安全产品，及时防范此类新型威胁，避免企业资产失陷。联系人: wangkun-bd@360.cn



IoC



C2


yellowchinks.geek
yellowchinks.dyn
wearelegal.geek
tsengtsing.libre
techsupporthelpars.oss
respectkkk.geek
pepperfan.geek
peepeepoo.libre
obamalover.pirate
milfsfors3x[.]com
funnyyellowpeople.libre
fridgexperts[.]cc
forwardchinks[.]com
folded[.]in
doodleching[.]com
cookiemonsterboob[.]com
chinksdogeaters.dyn
chinkchink.libre
bladderfull.indy
blackpeeps.dyn
91.206.93.243
91.149.232.129
91.149.232.128
91.149.222.133
91.149.222.132
67.207.84.82
54.37.243.73
51.89.239.122
51.89.238.199
51.89.176.228
51.89.171.33
51.161.98.214
46.17.47.212
46.17.41.79
45.88.221.143
45.61.139.116
45.41.240.145
45.147.200.168
45.140.169.122
45.135.135.33
3.70.127.241
3.65.206.229
3.122.255.225
3.121.234.237
3.0.58.143
23.183.83.171
207.154.206.0
207.154.199.110
195.211.96.142
195.133.53.157
195.133.53.148
194.87.197.3
194.53.108.94
194.53.108.159
194.195.117.167
194.156.224.102
194.147.87.242
194.147.86.22
193.233.253.93
193.233.253.220
193.203.12.157
193.203.12.156
193.203.12.155
193.203.12.154
193.203.12.151
193.203.12.123
193.124.24.42
192.46.225.170
185.45.192.96
185.45.192.227
185.45.192.212
185.45.192.124
185.45.192.103
185.198.57.95
185.198.57.105
185.183.98.205
185.183.96.7
185.143.221.129
185.143.220.75
185.141.27.238
185.141.27.234
185.117.75.45
185.117.75.34
185.117.75.119
185.117.73.52
185.117.73.147
185.117.73.115
185.117.73.109
18.185.188.32
18.136.209.2
178.62.204.81
176.97.210.176
172.105.59.204
172.105.55.131
172.104.108.53
170.187.187.99
167.114.124.77
165.227.19.36
159.65.158.148
159.223.39.133
157.230.15.82
15.204.18.232
15.204.18.203
15.204.128.25
149.56.42.246
139.99.166.217
139.99.153.49
139.99.142.215
139.162.69.4
138.68.10.149
137.74.65.164
13.229.98.186
107.181.160.173
107.181.160.172




Reporter


kvsolutions[.]ru
icarlyfanss[.]com




Samples


ea7945724837f019507fd613ba3e1da9
899047ddf6f62f07150837aef0c1ebfb
0f781868d4b9203569357b2dbc46ef10


{"version":"0.3.1","atoms":[],"cards":[["markdown",{"markdown":"# 背景\n\n2022年4月13日，360Netlab首次向社区披露了Fodcha僵尸网络，在我们的文章发表之后，Fodcha遭受到相关部门的打击，其作者迅速做出回应，在样本中留下``Netlab pls leave me alone I surrender``字样向我们投降。本以为Fodcha会就此淡出江湖，没想到这次投降只是一个**不讲武德的假动作**，Fodcha的作者在诈降之后并没有停下更新的脚步，很快就推出了新版本。\n\n在新版本中，Fodcha的作者重新设计了通信协议，并开始使用xxtea和chacha20算法对敏感资源和网络通信进行加密，以躲避文件&流量层面的检测；同时引入了**OpenNIC 域名**做为主选C2，**ICANN 域名**做为后备C2的双C2方案。这种冗余机制，既能防止C2被接管，又有良好的健壮性，能够维持其主控网络的稳定。\n\n依托于背后团队强大的N-day漏洞整合能力，卷土重来的Focha与之前对比可谓有过之而无不及。在我们的数据视野中，**从规模来看**，Fodcha再次发展成日活Bot节点数超过60K，C2域名绑定40+IP，可以轻松打出超过**1Tbps**流量的大规模僵尸网络；**就活跃程度而言**，Fodcha日均攻击目标100+，累计攻击目标2万多，在10月11日到达了攻击的巅峰，单日“**丧心病狂**”的攻击了**1396个目标**。\n\n在极短的时间内重回巅峰，Fodcha的作者似乎忘了闷声发大财的道理，竟然又开始主动\"招惹”我们，在某次扫描的脚本中使用``N3t1@bG@Y``字样的leetspeak，翻译过来就是\"``NETLABGAY``\"，这么明目张胆的黑Netlab，让我们觉得它多多少少有些“皮痒”了。\n\n鉴于Fodcha的规模&活跃程度带来的巨大危险性，以及非常嚣张的挑衅，我们决定撰写本文向社区分享我们的发现，一起打击Fodcha的嚣张气焰，共同维护网络安全。\n\n# 时间线\n\n依托于360Netlab强大的BotMon和DDoSMon系统，我们对Fodcha的样本演变和DDoS攻击指令一直保持着良好跟踪，下面是我们看到的样本演变以及一些重要的DDoS攻击事件。（注：Fodcha样本本身没有特定的标志表明其版本，这是我们内部为了跟踪方便而定的版本号）\n\n* 2022年1月12日，首次捕获到Fodcha僵尸网络样本。\n\n* 2022年4月13日，首次向外披露Fodcha僵尸网络，包含版本V1，V2。\n\n* 2022年4月19日，捕获版本V2.x，使用**OpenNIC's TLDs风格的C2**（全文简称OpenNIC C2）。\n\n* 2022年4月24日，捕获版本V3，使用xxtea算法加密配置信息，新增**ICANN's TLDs风格的C2**（全文简称ICANN C2），和OpenNIC C2构成冗余机制；新增反沙箱&反调试机制。\n\n* 2022年6月5日，捕获版本V4，使用结构化的配置信息，去除反沙箱&反调试机制。\n\n* 2022年6月7&8日，监控到Fodcha对**某国的某地的健康码机构**进行了DDoS攻击。\n\n* 2022年7月7日，捕获版本V4.x，额外新增一组ICANN C2。\n\n* 2022年9月X日，在协助**某国的某执法机构**固定某公司语音业务被DDoS攻击的证据链过程中，发现攻击背后有Fodcha的影子。\n\n* 2022年9月21日，**某知名云服务商**就一起流量**超过1Tbps**的攻击事件向我们咨询，经过数据的交叉比对，确定攻击方为Fodcha。\n\n  \n\n# 规模推测\n国外合作伙伴的数据表明Fodcha 4月份时全球日活Bot的数量为6W([参考我们另一篇文章](__GHOST_URL__/fodcha-a-new-ddos-botnet/))，关于Fodcha僵尸网络的目前规模，我们没有确切的数字，但通过对比Fodcha 4月和10月在C2 IP数量上的差异，我们从技术上出发，有个未经验证的猜测：目前Fodcha的日活Bot数量超过6W。\n\n推测过程如下：\n僵尸网络的规模与C2 IP的数量存在一个正向关系，最朴素的观点是：“僵尸网络规模越大，所需要的C2基础设施也越多”。在4月份，Fodcha被处置之前，其作者为维持6W的规模，投入了10个C2 IP；随后Fodcha开始了自己的复活之旅，我们观察到一个现象，随着Fodcha的复苏，其C2域名对应的IP在持续增加。时至今日，Fodcha的作者投入了多少C2 IP呢？使用dig命令查询最新的C2域名``yellowchinks.dyn``的绑定IP，可以看到数量是44。\n<a href=\"__GHOST_URL__/content/images/2022/10/fodcha_c2infras.png\"><img src=\"__GHOST_URL__/content/images/2022/10/fodcha_c2infras.png\" class=\"kg-image\"/></a>\n\n可以说我们见证了Fodcha的C2 IP一步步从几个增长到今天的40+，可能的解释是作者人傻钱多无脑上资源，但结合其迅猛的传播以及历史上曾看到的万级规模，他们增加C2 IP更可能的原因是因为其僵尸网络规模太大，需要投入更多的IP资源，以使Bot与C2之间在数量上有一个合理比例，达到负载均衡。\n\n综上，我们从C2 IP数量上大幅度的增长，推测目前Fodcha的规模大于4月份，日活Bot数量超过6W。当然**再合理的推测也还是假设**，欢迎有视野的社区伙伴**不吝指正**。\n\n\n \n# DDoS统计\n\n回到C2 IP 44这个数字本身，纵然我们和僵尸网络battle多年见多识广，但这个数字依然让我们感到惊讶。世上没有无缘故的爱，光是这些IP资源，就得花费不少的，Fodcha的作者为什么愿意花这个钱呢？答案是DDoS攻击让他赚到了钱。我们节选了2022年6月29至今的数据，其攻击趋势和目标区域分布如下：\n\n<a href=\"__GHOST_URL__/content/images/2022/10/image--1-.png\"><img src=\"__GHOST_URL__/content/images/2022/10/image.min-1.png\" class=\"kg-image\"/></a>\n可以看出：\n\n* 无愧于DDoS狂魔的称号，攻击几乎没有停歇，几乎打遍全球，日均攻击事件1K+。\n\n\n* 中美两国颜色较深，说明两国累计被攻击目标及次数较多，综合考虑到两国在互联网上业务的比重原本就比较大，这里的“看起来多”是一种正常状况。\n\n攻击指令在7天内的时间分布如下所示，可以看出Fodcha发起的DDoS攻击遍及**7 * 24**小时，没有明显的时区性，我们倾向Fodcha是一个商业驱动的僵尸网络。\n\n<a href=\"__GHOST_URL__/content/images/2022/10/fodcha_instimezone.png\"><img src=\"__GHOST_URL__/content/images/2022/10/fodcha_instimezone.png\" class=\"kg-image\"/></a>\n\n\n# 样本分析\n\n我们将捕获的样本分成了４个大版本，其中在上一篇blog中已经分析过V1V2，此处就不再赘述了，本文选取最新的V4系列样本为主要分析对象，它们的基本信息如下所示：\n\n```\nMD5: ea7945724837f019507fd613ba3e1da9\nELF 32-bit LSB executable, ARM, version 1, dynamically linked (uses shared libs), stripped\nLIB: uclibc\nPACKER: None\nversion: V4\n\nMD5: 899047ddf6f62f07150837aef0c1ebfb\nELF 32-bit LSB executable, ARM, version 1 (SYSV), statically linked, stripped\nLib: uclibc\nPacker: None\nVersion: V4.X\n```\n\nFodcha的Bot在被侵入设备运行时，首先会从``运行参数``，``网络的连通性``，``是否设置“LD_PRELOAD”环境变量``，``自身是否被调试``等方面进行检查，如果不满足要求就直接退出，这些检查可以看成是一种对通过模拟器&沙箱提取IOC的简单对抗。\n\n当满足要求运行要求时，则首先解密出配置信息，在Console上输出**snow slide**，然后就是一些常见的主机行为，如单一实例，进程名伪装，操控watchdog，清空特定端口进程，上报特定进程信息等，我们认为这些主机侧的功能没有太多亮点，因此不再展开分析，下文将着重从解密配置信息，网络通信，DDoS攻击等方面对Fodcha进行剖析。\n\n\n\n## 解密配置信息(Config)\n\nFodcha在V2.X，V3使用并列的Config组织方式，而在V4,V4.X中则使用结构化的Config组织方式，下图非常清楚的显示了它们的区别。\n\n\n\n<a href=\"__GHOST_URL__/content/images/2022/10/fodcha_disconfig.png\"><img src=\"__GHOST_URL__/content/images/2022/10/fodcha_disconfig.png\" class=\"kg-image\"/></a>\n\n\n\n虽然Config的组织方法不一样，但它们的加密方法是一样的，通过下面代码片段引用的常量可知，它们使用的是xxtea算法，密钥为``PJbiNbbeasddDfsc``。\n\n<a href=\"__GHOST_URL__/content/images/2022/10/fodcha_xxtea.png\"><img src=\"__GHOST_URL__/content/images/2022/10/fodcha_xxtea.png\" class=\"kg-image\"/></a>\n\n经过逆向，我们编写了以下IDAPYTHON脚本来解密配置信息。\n\n```\n# md5: ea7945724837f019507fd613ba3e1da9\n# requirement: pip install xxtea-py\n# test: ida7.6_python3\n\nimport ida_bytes\nimport xxtea\n\nBufBase=0x1F2B0\nConfBase=0x0001F1A0\nkey=b\"PJbiNbbeasddDfsc\"\nfor i in range(17):\n    offset=ida_bytes.get_word(i*16+ConfBase+2)\n    leng=ida_bytes.get_word(i*16+ConfBase+4)-offset\n    buf=ida_bytes.get_bytes(BufBase+offset,leng)\n    print(\"index:%d, %s\" %(i,xxtea.decrypt(buf,key)))\n```\n\n解密后的Config信息如下表所示，可以看到index 11还保留着“投降”的彩蛋，另外值得一提的是index 12，它是reporter服务器地址，Fodcha会将一些特定进程的信息上报给它。\n\n| Index | Value                                                        |\n| ----- | ------------------------------------------------------------ |\n| 0     | snow slide                                                   |\n| 1     | /proc/                                                       |\n| 2     | /stat                                                        |\n| 3     | /proc/self/exe                                               |\n| 4     | /cmdline                                                     |\n| 5     | /maps                                                        |\n| 6     | /exe                                                         |\n| 7     | /lib                                                         |\n| 8     | /usr/lib                                                     |\n| 9     | .ri                                                          |\n| 10    | GET /geoip/?res=10&r HTTP/1.1\\r\\nHost: 1.1.1.1\\r\\nConnection: Close\\r\\n\\r\\n |\n| 11    | Netlab pls leave me alone I surrender                        |\n| 12    | kvsolutions.ru                                               |\n| 13    | api.opennicproject.org                                       |\n| 14    | watchdog                                                     |\n| 15    | /dev/                                                        |\n| 16    | TSource Engine Query                                         |\n\n\n\n## 网络通信\n\nFodcha的网络通信在代码层面有一个非常固定的特点：一个永真的While循环，通过switch-case进行各个阶段的处理，因此Fodcha各个版本的网络协议处理函数在IDA中产生的CFG图高度相似，这个特点可以帮助我们对样本进行辨别，对功能快速定位。\n\n\n<img src=\"__GHOST_URL__/content/images/2022/10/fodcha_cfg.png\"  width=\"860px\" /> \n\n总的来说，Fodcha的网络通信要经过以下4个步骤：\n\n1. 解密C2\n2. DNS查询\n3. 建立通信\n4. 执行指令\n\n\n\n###　0x1: 解密C2\n\nFodcha的不同版本支持的C2种类是不一样的，V2.X只有1组OpenNIC C2；V3&V4拥有1组OpenNIC C2，1组ICANN C2；而V4.X则是最多的，1组OpenNIC C2，2组ICANN C2，下面的图非常清楚的显示了它们的区别。\n\n\n\n\n<a href=\"__GHOST_URL__/content/images/2022/10/fodcha_c2_dis.png\"><img src=\"__GHOST_URL__/content/images/2022/10/fodcha_c2_dis.png\" class=\"kg-image\"/></a>\n\n虽然C2种类&数量不一样，但是它们的处理逻辑如下图所示，几乎是一样的，首先通过C2_GET函数获得一个C2域名，然后通过DNS_QUERY函数获得C2对应的IP，其中C2_GET的第一个参数为C2密文数据，第2个参数为长度，而DNS_QUERY的第2个参数则暗示了C2的类型。\n\n\n<img src=\"__GHOST_URL__/content/images/2022/10/FODCHA_c2compose.png\"  width=\"860px\" /> \n\n通过C2_GET可以获得一个有效的C2域名，它内部的实现可以分成2步：\n* 首先得解密C2密文数据。\n* 然后将它们构造成一个合法的域名。\n\n### 解密C2密文数据\n\nC2的密文数据使用了配置信息一样的加密方式，即xxtea，密钥也是**PJbiNbbeasddDfsc**，通过下面简单的IDAPYTHON脚本，即可解密出OpenNic C2数据。\n\n```\n#md5: 899047DDF6F62F07150837AEF0C1EBFB\nimport xxtea\nimport ida_bytes\nimport hexdump\nkey=b\"PJbiNbbeasddDfsc\"\nbuf=ida_bytes.get_bytes(0x0001CA6C,1568)  # Ciphertext of OpenNic C2\nplaintext=xxtea.decrypt(buf,key)\nprint(plaintext)\n```\n\n解密后的C2数据如下图所示，可以看出C2数据由2部分组成，前面的是domain names，后面是TLDs，它们通过红框中的“**/**”符号分隔。\n\n\n<img src=\"__GHOST_URL__/content/images/2022/10/fodcha_c2plaintext.png\"  width=\"860px\" /> \n\n### 构造域名\n\nFodcha有一个特定的域名构造方法，等效的Python实现如下所示：\n\n```\n# md5: 899047ddf6f62f07150837aef0c1ebfb\n# requirement: pip install xxtea-py\n# test: ida7.6_python3\n\nimport xxtea\nimport ida_bytes\n\ndef getcnt(length):\n    cnt=1\n    while True:\n        cnt +=1\n        calc=2\n        \n        for i in range(1,cnt):\n            calc+=2+12*i%cnt\n                    \n        if calc +cnt==length-1:\n            return cnt\n\n                        \nkey=b\"PJbiNbbeasddDfsc\"\nbuf=ida_bytes.get_bytes(0x0001CA6C,1568)  # Ciphertext of OpenNic C2\nplaintext=xxtea.decrypt(buf,key)\n\ndomains,tlds=plaintext.split(b'/')\ndomainList=domains.split(b',')\ntldList=tlds.split(b',')\n\ncnt=getcnt(len(domainList))\n\nprint(\"------------There're %d C2------------\" %cnt)\ncoff=2\nfor i in range(0,cnt):\n    if i ==0:\n        c2Prefix=domainList[i+coff]\n    else:\n        coff+=12*i %cnt+2\n        c2Prefix=domainList[i+coff]\n    c2Tld=tldList[(cnt-i-1)*3]\n    print(c2Prefix + b'.' + c2Tld)\n\n```\n\n将上文得到的C2数据做为输入，最终构造出以下14个OpenNIC C2。\n\n```\ntechsupporthelpars.oss\nyellowchinks.geek\nyellowchinks.dyn\nwearelegal.geek\nfunnyyellowpeople.libre\nchinksdogeaters.dyn\nblackpeeps.dyn\npepperfan.geek\nchinkchink.libre\npeepeepoo.libre\nrespectkkk.geek\nbladderfull.indy\ntsengtsing.libre\nobamalover.pirate\n```\n\n对ICANN域名体系熟悉的读者，或许会在第一眼就认为我们的解密是错误的，因为ICANN的域名体系并不支持这些TLDs，它们肯定“无法解析”，事实上它们正是OpenNIC体系下的域名，OpenNIC是独立于ICANN的另一套域名体系，它支持下图所示的TLDs，OpenNIC的域名无法通过常见的DNS(如8.8.8.8，101.198.198.198)解析，必须使用指定的NameServer，更多的细节就不再展开，感兴趣的读者自行到其[**官方网站**](https://www.opennic.org/)了解。\n\n\n<img src=\"__GHOST_URL__/content/images/2022/10/fodcha_opennic.png\"  width=\"860px\" /> \n\n用同样的方法，我们可以得到以下4个ICANN C2。\n\n```\ncookiemonsterboob[.]com\nforwardchinks[.]com\ndoodleching[.]com\nmilfsfors3x[.]com\n```\n\n### 0X2: DNS查询\n\n当成功获得C2域名后，Bot通过函数**DNS_QUERY**进行域名解析，它的第2个参数是一个FLAG，暗示了OpenNIC/ICANN C2的不同处理过程，相应的代码片段如下所示：\n\n\n\n<img src=\"__GHOST_URL__/content/images/2022/10/fodcha_disdns.png\"  width=\"860px\" /> \n\n可以看出对于OpenNIC C2的解析有2个选择：\n\n* 选择1：通过API接口向**api.opennicproject.org**请求，动态的获取nameserver\n\n\n<img src=\"__GHOST_URL__/content/images/2022/10/fodcha_resolvns.png\"  width=\"860px\" /> \n\n\n* 选择2：使用下图所示的硬编码nameserver\n\n<img src=\"__GHOST_URL__/content/images/2022/10/fodcha_opennicHard.png\"  width=\"860px\" /> \n\n\n而对于ICANN C2则只有一个选择，即使用下图中的硬编码nameserver。\n\n<img src=\"__GHOST_URL__/content/images/2022/10/fodcha_iccanHard.png\"  width=\"860px\" /> \n\n\n\n以实际解析 C2“techsupporthelpars.oss”为例，它的解析过程在网络流量中的体现如下所示：\n\n<a href=\"__GHOST_URL__/content/images/2022/10/fodcha_opendnsexample.png\"><img src=\"__GHOST_URL__/content/images/2022/10/fodcha_opendnsexample.png\" class=\"kg-image\"/></a>\n\n### 为什么使用OpenNIC / ICANN 双C2?\n\nFodcha作者构建了一套OpenNIC / ICANN 双C2的冗余结构，他为什么要这么做呢？\n\n从C2基础设施的角度出发，Fodcha被曝光后，其C2被一些服务商加入到了监控列表，进行拦截。例如Quad9DNS（9.9.9.9）就曾发过一个关于Fodcha域名流量spike的Twitter\n\n<img src=\"__GHOST_URL__/content/images/2022/10/fodcha_quad.png\"  width=\"860px\" /> \n\n\n在Fodcha被打击之后，其作者在重新选择C2基础设施时，看中了OpenNIC宣传的\"DNS Neutrality\"特性，通过绕开ICANN的域名体系，从根本上消除C2被监管&接管的可能性，因此Fodcha在V2.X引入OpenNic C2，并将其做为主C2。\n\n与此同时，OpenNIC C2可能存在一些问题，比如OpenNIC的NameServer在某些地区可能无法访问，或者域名解析上存在效率或稳定性的问题。出于健壮性的考虑，Fodcha作者在V3之 后重新加入ICANN C2作为后备C2，与主C2构成冗余结构。\n\n\n\n### 0x3: 建立通信\n\nFodcha Bot通过又下代码片段和C2建立连接，一共有个22个端口。\n\n<img src=\"__GHOST_URL__/content/images/2022/10/fodcha_establishConn.png\"  width=\"860px\" /> \n\n\n\n当成功和C2建立连接后，Bot与C2必须经过3个阶段的交互，才能真正建立通信。\n\n* 阶段1：Bot向C2请求chacha20加密算法的的key&nonce。\n* 阶段2：Bot与C2使用阶段1的key&nonce进行身份确认。\n* 阶段3：Bot将加密后的上线&分组信息发往C2。\n\n为了辅助分析，我们在受限的环境内运行了Bot样本，并使用`fsdsaD`做为分组字串，产生了下图所示的网络流量，下文将详细介绍此流量是如何生成的。\n\n\n\n<img src=\"__GHOST_URL__/content/images/2022/10/fodcha_prapacket.png\"  width=\"860px\" /> \n\n###　阶段1：Bot ---> C2 ,格式为head(7 bytes) + body( random 20-40 bytes)\n\nBot主动向C2发送**netstage=6**的初始化消息，这个消息的格式为head+body，各字段含义如下所示：\n\n\n<img src=\"__GHOST_URL__/content/images/2022/10/fodcha_netStageOneb2c.png\"  width=\"860px\" /> \n\n####　head\n\nhead的长度为7 bytes，格式如下所示：\n\n```\n06     \t\t---->netstage,1byte,06 means init\nf0 70       ---->tcpip checksum, 2byte, \n00 16\t\t---->length of body, 2 bytes\n```\n\n#### checksum\n\nhead中的checksum使用的是tcp/ip的checksum，它计算对象为整个payload，checksum所在偏移的原始值为\"\\x00\\x00\"，checksum的python实现如下所示： \n\n```python\ndef checksum(data):\n    s = 0\n    n = len(data) % 2\n    for i in range(0, len(data)-n, 2):\n        s+= ord(data[i]) + (ord(data[i+1]) << 8)\n    if n:\n        s+= ord(data[-1])\n    while (s >> 16):\n        s = (s & 0xFFFF) + (s >> 16)\n        s = ~s & 0xffff\n    return s\n\nbuf=\"\\x06\\x00\\x00\\x00\\x00\\x00\\x16\\x36\\x93\\x93\\xb7\\x27\\x5c\\x9a\\x2a\\x16\\x09\\xd8\\x13\\x32\\x01\\xd2\\x69\\x1d\\x25\\xf3\\x42\\x00\\x32\"\nprint(hex(checksum(buf)))\n\n#hex(checksum(buf))\n#0x70f0\n```\n\n#### body\n\nbody为随机生成的内容，无意义。\n\n```\n00000000  36 93 93 b7 27 5c 9a 2a 16 09 d8 13 32 01 d2 69\n00000010  1d 25 f3 42 00 32\n```\n\n\n\n\n\n### 阶段1：C2--->Bot，共2轮 \n\n当C2收到Bot的**netstage=6**的消息后，就会向BOT发送2轮的数据。\n\n\n<img src=\"__GHOST_URL__/content/images/2022/10/fodcha_netStageOne.png\"  width=\"860px\" /> \n\n* 第一轮，36 bytes , 原信息被xxtea加密，解密后作为chacha20的key，长度为32bytes \n\n  ```python\n  import hexdump\n  import xxtea\n  key=b\"PJbiNbbeasddDfsc\"\n  keyBuf=bytes.fromhex(\"806d8806cd5460d8996339fbf7bac34ba1e20f792872ba0e05d096ad92a5535e60e55b8d\")\n  chaKey=xxtea.decrypt(keyBuf,key)\n  hexdump.hexdump(chaKey)\n  \n  #chaKey\n  00000000: E6 7B 1A E3 A4 4B 13 7F  14 15 5E 99 31 F2 5E 3A\n  00000010: D7 7B AB 0A 4D 5F 00 EF  0C 01 9F 86 94 A4 9D 4B\n  \n  ```\n\n  \n\n* 第二轮，16 bytes，原信息被xxtea加密，解密后作为chacha20的nonce，长度12bytes\n\n  ```python\n  import hexdump\n  import xxtea\n  key=b\"PJbiNbbeasddDfsc\"\n  nonBuf=bytes.fromhex(\"22c803bb310c5b2512e76a472418f9ee\")\n  chaNonce=xxtea.decrypt(nonBuf,key)\n  hexdump.hexdump(chaNonce)\n  \n  #chaNonce\n  00000000: 98 79 59 57 A8 BA 7E 13  59 9F 59 6F\n  ```\n\n  \n\n### 阶段2：Bot--->C2，chacha20加密\n\nBot收到chacha20的key和nonce后，就向C2发送**netstage=4**的消息，此次消息使用chacha20加密，key&nonce由上一阶段获得，加密的轮数为1。\n\n<img src=\"__GHOST_URL__/content/images/2022/10/fodcha_netStageTwob2c.png\"  width=\"860px\" /> \n\n\n我们可以使用下面的python代码可以解密上面的流量，\n\n```\nfrom Crypto.Cipher import ChaCha20\ncha=ChaCha20.new(key=chaKey,nonce=chaNonce)\ncha.seek(64)\ntmp=bytes.fromhex('dc23c56943431018b61262481ce5a219da9480930f08714e017edc56bf903d32ac5daeb8314f1bf7e6')\nrnd3=cha.decrypt(tmp)\n```\n\n解密后的流量如下所示，它的格式依然是前文所述的head（7 bytes）+body，其中head的netstage字段的值为04，代表身份认证。\n\n<img src=\"__GHOST_URL__/content/images/2022/10/fodcha_netplainb2c.png\"  width=\"860px\" /> \n\n\n### 阶段2：C2--->Bot，chacha20加密\n\nC2在收到Bot的身份认证消息后，也向Bot的数据发送**netstage=4**的消息，同样使用chacha20加密，且key,nonce,轮数和Bot使用的是一样的。\n\n<img src=\"__GHOST_URL__/content/images/2022/10/fodcha_netStageTwoc2b.png\"  width=\"860px\" /> \n\n\n使用和Bot相同的代码解密流量，可以看出它的格式也是head+body，netstage的值也为04。\n\n<img src=\"__GHOST_URL__/content/images/2022/10/fodcha_netplainc2b.png\"  width=\"860px\" /> \n\n\n在Bot和C2互发**netstage=4**的消息之后，代表阶段1的chacha20 key&nonce被双方认可，彼此的身份认证完成，Bot进入下一阶段准备上线。\n\n### 阶段3：Bot--->C2，共2轮，chacha加密\n\nBot向C2发送**netstage=5**的消息，表示准备上线，接着再自己的分组信息上报给C2，这2轮消息也使用chacha20加密。\n\n* 第一轮\n   <img src=\"__GHOST_URL__/content/images/2022/10/fodcha_netStageThrReg.png\"  width=\"860px\" /> \n  \n\n* 第二轮\n\n   <img src=\"__GHOST_URL__/content/images/2022/10/fodcha_netStageThrGroup.png\"  width=\"860px\" /> \n  \n\n\n\n上述2轮的数据解密后如下所示，可以看出分组的内容正是预设的\"``fsdsaD``\"，这代表我们的分析是正确的，至此Bot成功上线，开始等待执行C2下发的指令。\n\n\n<img src=\"__GHOST_URL__/content/images/2022/10/fodcha_netplainb2cReg.png\"  width=\"860px\" /> \n\n\n### 0x4:执行指令\n\nBot成功上线后，支持的netstage编号，如下所图所示，其中最重要的就是**netstage=1**代表DDoS任务，Fodcha复用了大量Mirai的攻击代码，一共支持17种攻击方法。\n\n\n<img src=\"__GHOST_URL__/content/images/2022/10/fodcha_afterreg.png\"  width=\"860px\" /> \n\n以下图的DDos_Task流量（netstage=01）为例：\n\n\n<img src=\"__GHOST_URL__/content/images/2022/10/fodcha_taskddos.png\"  width=\"860px\" /> \n\n攻击指令依然采用chacha20加密，解密后的指令如下所示，相信熟悉Mirai的读者看到此处肯定会心一笑。\n\n```\n00000000: 00 00 00 3C 07 01 xx 14  93 01 20 02 00 00 02 01\n00000010: BB 01 00 02 00 01\n```\n\n上述攻击指令的格式和解析方式如下表所示：\n\n| offset | len (bytes) | value          | meaning                                                  |\n| ------ | ----------- | -------------- | -------------------------------------------------------- |\n| 0x00   | 4           | 00 00 00 3c    | Duration                                                 |\n| 0x04   | 1           | 07             | Attack Vector，07                                        |\n| 0x05   | 1           | 1              | Attack Target Cnt                                        |\n| 0x06   | 4           | xx 14  93 01   | Attack Target，xx.20.147.1                               |\n| 0x0a   | 1           | 20             | Netmask                                                  |\n| 0x0b   | 1           | 02             | Option Cnt                                               |\n| 0x0c   | 5           | 00 00 02 01 bb | OptionId 0，len 2, value 0x01bb ---> (port 443)          |\n| 0x11   | 5           | 01 00 02 00 01 | OptionId 1, len 2, value 0x0001---> (payload len 1 byte) |\n\n当Bot接收到上述指令，就会使用payload为1字节的tcp报文对目标xx.20.147.1:443进行DDoS攻击，这和实际抓包的流量是能对应上的。\n\n<a href=\"__GHOST_URL__/content/images/2022/10/fodcha_ddospacket.png\"><img src=\"__GHOST_URL__/content/images/2022/10/fodcha_ddospacket.png\" class=\"kg-image\"/></a>\n# 花絮\n\n### 0x01: 种族歧视\n\n从某些OpenNIC C2的构词上来说，Fodcha的作者似乎对黄种人，黑人有比较大的敌意。\n```\nyellowchinks.geek\nwearelegal.geek\nfunnyyellowpeople.libre\nchinksdogeaters.dyn\nblackpeeps.dyn\nbladderfull.indy\n\nwehateyellow\n```\n\n### 0x02: 攻击即勒索\n\nFodcha曾在其下发的UDP攻击指令中，附带以下字串：\n\n```\nsend 10 xmr to 49UnJhpvRRxDXJHYczoUEiK3EKCQZorZWaV6HD7axKGQd5xpUQeNp7Xg9RATFpL4u8dzPfAnuMYqs2Kch1soaf5B5mdfJ1b or we will shutdown your business\n```\n\nBot打出的攻击流量如下所示，该钱包地址似乎是非法的，没能给我们更多的线索，但从这一行为出发，或许Fodcha背后的运营者正在尝试攻击即勒索这种商业模式。\n<a href=\"__GHOST_URL__/content/images/2022/10/fodcha_ddosransom.png\"><img src=\"__GHOST_URL__/content/images/2022/10/fodcha_ddosransom.png\" class=\"kg-image\"/></a>\n\n# 联系我们\n感兴趣的读者，可以在 [twitter](https://twitter.com/360Netlab) 或者通过邮件netlab[at]360.cn联系我们。\n\n# 解决方案\n基于Netlab多年研究工作孵化的360全系列[DNS安全产品](https://sdns.360.net/)均已支持文中远控服务器的拦截和检测，同时内置多种算法可有效发现和拦截各种未知威胁，建议企业客户接入360 DNS安全SaaS平台或部署本地360DNS安全产品，及时防范此类新型威胁，避免企业资产失陷。联系人: wangkun-bd@360.cn\n\n# IoC\n### C2\n\n```\nyellowchinks.geek\nyellowchinks.dyn\nwearelegal.geek\ntsengtsing.libre\ntechsupporthelpars.oss\nrespectkkk.geek\npepperfan.geek\npeepeepoo.libre\nobamalover.pirate\nmilfsfors3x[.]com\nfunnyyellowpeople.libre\nfridgexperts[.]cc\nforwardchinks[.]com\nfolded[.]in\ndoodleching[.]com\ncookiemonsterboob[.]com\nchinksdogeaters.dyn\nchinkchink.libre\nbladderfull.indy\nblackpeeps.dyn\n91.206.93.243\n91.149.232.129\n91.149.232.128\n91.149.222.133\n91.149.222.132\n67.207.84.82\n54.37.243.73\n51.89.239.122\n51.89.238.199\n51.89.176.228\n51.89.171.33\n51.161.98.214\n46.17.47.212\n46.17.41.79\n45.88.221.143\n45.61.139.116\n45.41.240.145\n45.147.200.168\n45.140.169.122\n45.135.135.33\n3.70.127.241\n3.65.206.229\n3.122.255.225\n3.121.234.237\n3.0.58.143\n23.183.83.171\n207.154.206.0\n207.154.199.110\n195.211.96.142\n195.133.53.157\n195.133.53.148\n194.87.197.3\n194.53.108.94\n194.53.108.159\n194.195.117.167\n194.156.224.102\n194.147.87.242\n194.147.86.22\n193.233.253.93\n193.233.253.220\n193.203.12.157\n193.203.12.156\n193.203.12.155\n193.203.12.154\n193.203.12.151\n193.203.12.123\n193.124.24.42\n192.46.225.170\n185.45.192.96\n185.45.192.227\n185.45.192.212\n185.45.192.124\n185.45.192.103\n185.198.57.95\n185.198.57.105\n185.183.98.205\n185.183.96.7\n185.143.221.129\n185.143.220.75\n185.141.27.238\n185.141.27.234\n185.117.75.45\n185.117.75.34\n185.117.75.119\n185.117.73.52\n185.117.73.147\n185.117.73.115\n185.117.73.109\n18.185.188.32\n18.136.209.2\n178.62.204.81\n176.97.210.176\n172.105.59.204\n172.105.55.131\n172.104.108.53\n170.187.187.99\n167.114.124.77\n165.227.19.36\n159.65.158.148\n159.223.39.133\n157.230.15.82\n15.204.18.232\n15.204.18.203\n15.204.128.25\n149.56.42.246\n139.99.166.217\n139.99.153.49\n139.99.142.215\n139.162.69.4\n138.68.10.149\n137.74.65.164\n13.229.98.186\n107.181.160.173\n107.181.160.172\n```\n\n### Reporter\n```\nkvsolutions[.]ru\nicarlyfanss[.]com\n```\n### Samples\n```\nea7945724837f019507fd613ba3e1da9\n899047ddf6f62f07150837aef0c1ebfb\n0f781868d4b9203569357b2dbc46ef10\n```"}]],"markups":[],"sections":[[10,0],[1,"p",[]]],"ghostVersion":"3.0"}