卷土重来的DDoS狂魔:Fodcha僵尸网络再次露出獠牙

逆向病毒分析 2年前 (2022) admin
448 0 0

背景

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。

卷土重来的DDoS狂魔:Fodcha僵尸网络再次露出獠牙
可以说我们见证了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狂魔:Fodcha僵尸网络再次露出獠牙
可以看出:

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

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

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

卷土重来的DDoS狂魔:Fodcha僵尸网络再次露出獠牙
样本分析

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

MD5: ea7945724837f019507fd613ba3e1da9ELF 32-bit LSB executable, ARM, version 1, dynamically linked (uses shared libs), strippedLIB: uclibcPACKER: Noneversion: V4
MD5: 899047ddf6f62f07150837aef0c1ebfbELF 32-bit LSB executable, ARM, version 1 (SYSV), statically linked, strippedLib: uclibcPacker: NoneVersion: V4.X

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

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

解密配置信息(Config)

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

卷土重来的DDoS狂魔:Fodcha僵尸网络再次露出獠牙虽然Config的组织方法不一样,但它们的加密方法是一样的,通过下面代码片段引用的常量可知,它们使用的是xxtea算法,密钥为PJbiNbbeasddDfsc。
卷土重来的DDoS狂魔:Fodcha僵尸网络再次露出獠牙
经过逆向,我们编写了以下IDAPYTHON脚本来解密配置信息。

md5: ea7945724837f019507fd613ba3e1da9requirement: pip install xxtea-pytest: ida7.6_python3import ida_bytesimport xxteaBufBase=0x1F2B0ConfBase=0x0001F1A0key=b”PJbiNbbeasddDfsc”for i in range(17):   offset=ida_bytes.get_word(i16+ConfBase+2)   leng=ida_bytes.get_word(i16+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.1rnHost: 1.1.1.1rnConnection: Closernrn
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图高度相似,这个特点可以帮助我们对样本进行辨别,对功能快速定位。

卷土重来的DDoS狂魔:Fodcha僵尸网络再次露出獠牙总的来说,Fodcha的网络通信要经过以下4个步骤:

  • 解密C2

  • DNS查询

  • 建立通信

  • 执行指令

    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,下面的图非常清楚的显示了它们的区别。
    卷土重来的DDoS狂魔:Fodcha僵尸网络再次露出獠牙
    虽然C2种类&数量不一样,但是它们的处理逻辑如下图所示,几乎是一样的,首先通过C2_GET函数获得一个C2域名,然后通过DNS_QUERY函数获得C2对应的IP,其中C2_GET的第一个参数为C2密文数据,第2个参数为长度,而DNS_QUERY的第2个参数则暗示了C2的类型。
    卷土重来的DDoS狂魔:Fodcha僵尸网络再次露出獠牙通过C2_GET可以获得一个有效的C2域名,它内部的实现可以分成2步:

  • 首先得解密C2密文数据。

  • 然后将它们构造成一个合法的域名。

解密C2密文数据

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

md5: 899047DDF6F62F07150837AEF0C1EBFBimport xxteaimport ida_bytesimport hexdumpkey=b”PJbiNbbeasddDfsc”buf=ida_bytes.get_bytes(0x0001CA6C,1568)  # Ciphertext of OpenNic C2plaintext=xxtea.decrypt(buf,key)print(plaintext)

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

卷土重来的DDoS狂魔:Fodcha僵尸网络再次露出獠牙构造域名

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

md5: 899047ddf6f62f07150837aef0c1ebfbrequirement: pip install xxtea-pytest: ida7.6_python3import xxteaimport ida_bytesdef 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 cntkey=b”PJbiNbbeasddDfsc”buf=ida_bytes.get_bytes(0x0001CA6C,1568)  # Ciphertext of OpenNic C2plaintext=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=2for i in range(0,cnt):   if i ==0:       c2Prefix=domainList[i+coff]   else:       coff+=12i %cnt+2       c2Prefix=domainList[i+coff]   c2Tld=tldList[(cnt-i-1)3]   print(c2Prefix + b’.’ + c2Tld)

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

techsupporthelpars.ossyellowchinks.geekyellowchinks.dynwearelegal.geekfunnyyellowpeople.librechinksdogeaters.dynblackpeeps.dynpepperfan.geekchinkchink.librepeepeepoo.librerespectkkk.geekbladderfull.indytsengtsing.libreobamalover.pirate

对ICANN域名体系熟悉的读者,或许会在第一眼就认为我们的解密是错误的,因为ICANN的域名体系并不支持这些TLDs,它们肯定“无法解析”,事实上它们正是OpenNIC体系下的域名,OpenNIC是独立于ICANN的另一套域名体系,它支持下图所示的TLDs,OpenNIC的域名无法通过常见的DNS(如8.8.8.8,101.198.198.198)解析,必须使用指定的NameServer,更多的细节就不再展开,感兴趣的读者自行到其官方网站了解。
卷土重来的DDoS狂魔:Fodcha僵尸网络再次露出獠牙用同样的方法,我们可以得到以下4个ICANN C2。

cookiemonsterboob[.]comforwardchinks[.]comdoodleching[.]commilfsfors3x[.]com

0X2: DNS查询
当成功获得C2域名后,Bot通过函数DNS_QUERY进行域名解析,它的第2个参数是一个FLAG,暗示了OpenNIC/ICANN C2的不同处理过程,相应的代码片段如下所示:
卷土重来的DDoS狂魔:Fodcha僵尸网络再次露出獠牙

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

  • 选择1:通过API接口向api.opennicproject.org请求,动态的获取nameserver

卷土重来的DDoS狂魔:Fodcha僵尸网络再次露出獠牙
  • 选择2:使用下图所示的硬编码nameserver

卷土重来的DDoS狂魔:Fodcha僵尸网络再次露出獠牙而对于ICANN C2则只有一个选择,即使用下图中的硬编码nameserver。

卷土重来的DDoS狂魔:Fodcha僵尸网络再次露出獠牙以实际解析 C2“techsupporthelpars.oss”为例,它的解析过程在网络流量中的体现如下所示:

卷土重来的DDoS狂魔:Fodcha僵尸网络再次露出獠牙
为什么使用OpenNIC / ICANN 双C2?

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

从C2基础设施的角度出发,Fodcha被曝光后,其C2被一些服务商加入到了监控列表,进行拦截。

例如Quad9DNS(9.9.9.9)就曾发过一个关于Fodcha域名流量spike的Twitter

卷土重来的DDoS狂魔:Fodcha僵尸网络再次露出獠牙
在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个端口。

卷土重来的DDoS狂魔:Fodcha僵尸网络再次露出獠牙
当成功和C2建立连接后,Bot与C2必须经过3个阶段的交互,才能真正建立通信。

  • 阶段1:Bot向C2请求chacha20加密算法的的key&nonce。

  • 阶段2:Bot与C2使用阶段1的key&nonce进行身份确认。

  • 阶段3:Bot将加密后的上线&分组信息发往C2。


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

卷土重来的DDoS狂魔:Fodcha僵尸网络再次露出獠牙
阶段1:Bot → C2 ,格式为head(7 bytes) + body( random 20-40 bytes)

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

卷土重来的DDoS狂魔:Fodcha僵尸网络再次露出獠牙head
head的长度为7 bytes,格式如下所示:

06             —→netstage,1byte,06 means initf0 70       —→tcpip checksum, 2byte,00 16        —→length of body, 2 bytes

checksum
head中的checksum使用的是tcp/ip的checksum,它计算对象为整个payload,checksum所在偏移的原始值为”x00x00”,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 sbuf=”x06x00x00x00x00x00x16x36x93x93xb7x27x5cx9ax2ax16x09xd8x13x32x01xd2x69x1dx25xf3x42x00x32”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 6900000010  1d 25 f3 42 00 32

阶段1:C2 –> Bot,共2轮
当C2收到Bot的netstage=6的消息后,就会向BOT发送2轮的数据。
卷土重来的DDoS狂魔:Fodcha僵尸网络再次露出獠牙

  • 第一轮,36 bytes , 原信息被xxtea加密,解密后作为chacha20的key,长度为32bytes

import hexdumpimport xxteakey=b”PJbiNbbeasddDfsc”keyBuf=bytes.fromhex(“806d8806cd5460d8996339fbf7bac34ba1e20f792872ba0e05d096ad92a5535e60e55b8d”)chaKey=xxtea.decrypt(keyBuf,key)hexdump.hexdump(chaKey)#chaKey00000000: E6 7B 1A E3 A4 4B 13 7F  14 15 5E 99 31 F2 5E 3A00000010: D7 7B AB 0A 4D 5F 00 EF  0C 01 9F 86 94 A4 9D 4B
  • 第二轮,16 bytes,原信息被xxtea加密,解密后作为chacha20的nonce,长度12bytes

import hexdumpimport xxteakey=b”PJbiNbbeasddDfsc”nonBuf=bytes.fromhex(“22c803bb310c5b2512e76a472418f9ee”)chaNonce=xxtea.decrypt(nonBuf,key)hexdump.hexdump(chaNonce)#chaNonce00000000: 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。

    卷土重来的DDoS狂魔:Fodcha僵尸网络再次露出獠牙

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

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

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

    卷土重来的DDoS狂魔:Fodcha僵尸网络再次露出獠牙

阶段2:C2 –> Bot,chacha20加密

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

    卷土重来的DDoS狂魔:Fodcha僵尸网络再次露出獠牙

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

    卷土重来的DDoS狂魔:Fodcha僵尸网络再次露出獠牙

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

阶段3:Bot-→C2,共2轮,chacha加密

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

  • 第一轮

  • 卷土重来的DDoS狂魔:Fodcha僵尸网络再次露出獠牙

  • 第二轮

  • 卷土重来的DDoS狂魔:Fodcha僵尸网络再次露出獠牙

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

    卷土重来的DDoS狂魔:Fodcha僵尸网络再次露出獠牙

0x4:执行指令

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

    卷土重来的DDoS狂魔:Fodcha僵尸网络再次露出獠牙

以下图的DDos_Task流量(netstage=01)为例:

    卷土重来的DDoS狂魔:Fodcha僵尸网络再次露出獠牙

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

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

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

offset
len
value meaning
0x00
4
00 00 00 3c
Duration
0x04
1
07
Attack Vector,7
0x05
1
1 Target Cnt
0x06
4
xx 14 93 01
Target
0x0a
1
20
Netmask
0x0b
1 02
Option Cnt
0x0c
5
00 00 02 01 bb
Option0, port
0x11
5 01 00 02 00 01
Option1

当Bot接收到上述指令,就会使用payload为1字节的tcp报文对目标xx.20.147.1:443进行DDoS攻击,这和实际抓包的流量是能对应上的。
卷土重来的DDoS狂魔:Fodcha僵尸网络再次露出獠牙
花絮

0x01: 种族歧视

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

yellowchinks.geekwearelegal.geekfunnyyellowpeople.librechinksdogeaters.dynblackpeeps.dynbladderfull.indywehateyellow

0x02: 攻击即勒索

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

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

Bot打出的攻击流量如下所示,该钱包地址似乎是非法的,没能给我们更多的线索,但从这一行为出发,或许Fodcha背后的运营者正在尝试攻击即勒索这种商业模式。
卷土重来的DDoS狂魔:Fodcha僵尸网络再次露出獠牙

原文始发于微信公众号(Netlab 三六零):卷土重来的DDoS狂魔:Fodcha僵尸网络再次露出獠牙

版权声明:admin 发表于 2022年10月27日 下午1:17。
转载请注明:卷土重来的DDoS狂魔:Fodcha僵尸网络再次露出獠牙 | CTF导航

相关文章

暂无评论

您必须登录才能参与评论!
立即登录
暂无评论...