On April 13, 2022, 360Netlab first disclosed the
Fodcha botnet. After our article was published, Fodcha suffered a crackdown from the relevant authorities, and its authors quickly responded by leaving
"Netlab pls leave me alone I surrender" in an updated sample.No surprise, Fodcha's authors didn't really stop updating after the fraudulent surrender, and soon a new version was released.
In the new version, the authors of Fodcha redesigned the communication protocol and started to use
chacha20 algorithms to encrypt sensitive resources and network communications to avoid detection at the file & traffic level; at the same time, a dual-C2 scheme with
OpenNIC domain as the primary C2 and
ICANN domain as the backup C2 was adopted.
Relying on the strong N-day vulnerability integration capabilities, the comeback of Focha is just as strong as the previous ones. In our data view, in terms of scale, Fodcha has once again developed into a massive botnet with more than
60K daily active bots and
40+ C2 IPs, we also observed it can easily launch more than 1Tbps DDos traffic; in terms of attacks, Fodcha has an average of
100+ daily attack targets and more than
20,000 cumulative attacks, on October 11, Fodcha hit its record and attacked
1,396 unique targets in that single day.
While Fodcha was busy attacking various targets, it has not forgot to mess with us, we saw it using
N3t1@bG@Y in one of it scan payload.
Backed by our
BotMon systems, we have kept good track of Fodcha's sample evolution and DDoS attack instructions, and below are the sample evolution and some important DDoS attack events we have seen. (Note: The Fodcha sample itself does not have a specific flag to indicate its version, this is the version number we use internally for tracking purposes)
On January 12, 2022, the first Fodcha botnet sample was captured.
April 13, 2022, Disclosure of the Fodcha botnet, containing versions V1, V2.
April 19, 2022, captured version V2.x, using
OpenNIC's TLDsstyle C2
April 24, 2022, version V3, using xxtea algorithm to encrypt configuration information, adding
ICANN's TLDsstyle C2, adding
June 5, 2022, version V4, using structured configuration information,
anti-debuggingmechanism were removed.
July 7, 2022, version V4.x with an additional set of
On September 21, 2022, a well-known cloud service provider was attacked with traffic exceeding
In April, we confirmed that the number of Fodcha's global daily live bots was about
60,000 (refer to our other article). We don’t have accurate number of the current size, but suspect that the number of current active bots has not dropped, maybe more than
There is a positive relationship between the size of a botnet and the number of C2 IPs, and the most parsimonious view is that "the larger the botnet, the more C2 infrastructure it requires. In April, there were
10 c2s to control the
60,000 bots; After that, we observed that the IPs corresponding to its C2 domains continued to increase. Using a simple dig command to query the latest C2 domain name
yellowchinks.dyn, we can see it resolves to
One likely reason for this is that their botnet is so large that they need to invest more IP resources in order to have a reasonable ratio between Bots and C2s to achieve load balancing.
More C2 IPs cost more money, and it seems that the business is good as it has been very active launching ddos attacks.We have excerpted the data from June 29, 2022 to the present, and the attack trends and target area distribution are as follows.
We can see that the ddos attacks has been non-stop, and China and US have the most targets.
The time distribution of the attack instructions within 7 days is shown below, which shows that Fodcha launched DDoS attacks throughout 7 * 24 hours, without any obvious working time zone.
We have divided the captured samples into four major versions, of which V1and
V2 have been analyzed in the previous blog, here we select the latest
V4 series samples as the main object of analysis, their basic information is shown below.
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
When Fodcha's Bot executes, it will first check
the operating parameters,
whether the "LD_PRELOAD" environment variable is set, and
whether it is debugged. These checks can be seen as a simple countermeasure to the typical emulator & sandbox.
When the requirements are met, it first decrypts the configuration information and print “snow slide” on the Console, then there are some common host behaviors, such as single instance, process name masquerading, manipulating watchdog, terminating specific port processes, reporting specific process information, etc. The following will focus on the decryption of configuration information, network communication, DDoS attacks and other aspects of Fodcha.
Decrypting configuration information (Config)
Fodcha uses a side-by-side Config organization in
V3, and a structured Config organization in
V4.X. The following figure clearly shows the difference.
Although the organization of Config is different, their encryption methods are the same. As we can see by the constants referenced in the code snippet below, they use the xxtea algorithm with the key
After inversion, we wrote the following
IDAPYTHON script to decrypt the configuration information.
# 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)))
The decrypted Config information is shown in the following table. You can see that index 11 still retains the aforementioned "surrender" egg, index 12 is worth mentioning, as it is the reporter server address to which Fodcha reports some process-specific information.
|10||GET /geoip/?res=10&r HTTP/1.1\r\nHost: 220.127.116.11\r\nConnection: Close\r\n\r\n|
|11||Netlab pls leave me alone I surrender|
|16||TSource Engine Query|
Fodcha's network communication has a very fixed feature at the code level: a perpetual While loop, with switch-case processing at each stage, so that the CFG graphs generated by each version of Fodcha's network protocol processing functions are highly similar in IDA.
In summary, Fodcha's network communication goes through the following four steps.
- Decryption C2
- DNS query
- Establishing communication
- Execute the command
0x1: Decrypting C2
Different versions of Fodcha support different types of C2. V2.X has only 1 group of OpenNIC C2; V3 & V4 have 1 group of OpenNIC C2 and 1 group of ICANN C2; and V4.X has the most, 1 group of OpenNIC C2 and 2 groups of ICANN C2, the following diagram shows the difference very clearly.
Although the types & numbers of C2 are different, their processing logic is almost the same as shown in the figure below.
Firstly, a C2 domain name is obtained through the C2_GET function, and then the corresponding IP of C2 is obtained through the DNS_QUERY function, where the first parameter of C2_GET is the C2 ciphertext data, and the second parameter is the length, while the second parameter of DNS_QUERY implies the type of C2.
A valid C2 domain name can be obtained through C2_GET, and its internal implementation can be divided into 2 steps.
- First, the C2 ciphertext data must be decrypted.
- Then they are constructed into a legitimate domain name.
Decrypting C2 ciphertext data
The C2 ciphertext data uses the same encryption method as the configuration information, i.e. xxtea, and the key is also
PJbiNbbeasddDfsc. The OpenNic C2 data can be decrypted by the following simple IDAPYTHON script.
#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)
The decrypted C2 data is shown below, you can see that the C2 data consists of 2 parts, the front is the domain names, the back is the TLDs, they are separated by the "/" symbol in the red box.
Constructing a domain name
Fodcha has a specific domain name construction method, and the equivalent Python implementation is shown below.
# 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)
Taking the C2 data obtained above as input, the following 14 OpenNIC C2s are finally constructed.
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
Readers familiar with the ICANN domain name system may think at first glance that our decryption is wrong, because the ICANN domain name system does not support these TLDs, they would be "unresolvable", but in fact they are the domain names under the OpenNIC system, OpenNIC is independent of the OpenNIC, which supports the TLDs shown in the figure below. The domain names of OpenNIC cannot be resolved by common DNS (such as
18.104.22.168) and must use the specified NameServer. Readers can check out OpenNIC’s official website for more details.
Using the same method, we can get the following 4 ICANN C2s.
cookiemonsterboob[.]com forwardchinks[.]com doodleching[.]com milfsfors3x[.]com
0X2: DNS lookup
When the C2 domain name is successfully obtained, Bot performs the domain name resolution through the function
DNS_QUERY, its 2nd parameter is a FLAG, which implies the different processing of OpenNIC/ICANN C2, and the corresponding code snippet is shown below.
It can be seen that there are 2 options for the resolution of OpenNIC C2.
- Option 1: Request from
api.opennicproject.orgthrough API interface to get nameserver dynamically
- Option 2: Use the hard-coded nameserver shown in the figure below
For ICANN C2, there is only one option, i.e., use the hard-coded nameserver shown in the figure below.
The actual resolution of C2
techsupporthelpars.oss, for example, is reflected in the network traffic as follows.
Why use OpenNIC / ICANN dual C2?
Fodcha's author has built a redundant OpenNIC / ICANN dual-C2 architecture, why did he do so?
From a C2 infrastructure perspective, after Fodcha was exposed, its C2 was added to various security lists.
Quad9DNS (22.214.171.124), for example, had sent a tweet about Fodcha domain traffic spike
After Fodcha was cracked down, its author, when reselecting the C2 infrastructure, looked at the
DNS Neutrality feature touted by OpenNIC to eliminate the possibility of C2 being regulated & taken over.
At the same time, OpenNIC based C2 has it own problems, such as the NameServer of OpenNIC may not be accessible in some regions, or there are efficiency or stability problems in domain name resolution. For the sake of robustness, Fodcha authors re-added ICANN C2 as the backup C2 after V3 to form a redundant structure with the main C2.
0x3: Establishing communication
Fodcha Bot establishes a connection to C2 through the following code snippet, which has a total of 22 ports.
Once the connection with C2 is successfully established, the Bot and C2 must go through 3 phases of interaction before communication is actually established.
Stage 1: Bot requests the key&nonce of the chacha20 encryption algorithm from C2.
Stage 2: Bot and C2 use the key&nonce from stage 1 for identity confirmation.
Stage 3: Bot sends the encrypted upline & group information to C2.
To aid in the analysis, we ran the Bot sample within a restricted environment and used
fsdsaD as the packet string to generate the network traffic shown in the figure below, and the details of how this traffic was generated are described below.
Stage 1: Bot ---> C2 ,formatted as head(7 bytes) + body( random 20-40 bytes)
Bot actively sends an initialization message with
netstage=6 to C2, this message has the format of head+body, and the meaning of each field is shown below.
The length of head is 7 bytes, and the format is shown below.
06 ---->netstage,1byte,06 means init f0 70 ---->tcpip checksum, 2byte, 00 16 ---->length of body, 2 bytes
The checksum in head uses the tcp/ip checksum, which is calculated for the whole payload, and the original value of the checksum offset is
\x00\x00, and the python implementation of the checksum is as follows.
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 is a randomly generated content, meaningless.
00000000 36 93 93 b7 27 5c 9a 2a 16 09 d8 13 32 01 d2 69 00000010 1d 25 f3 42 00 32
Stage 1: C2-->Bot, 2 rounds
When C2 receives the message
netstage=6 from Bot, it will send 2 rounds of data to BOT.
The first round, 36 bytes , the original message is encrypted by xxtea and decrypted as the key of chacha20, with the length of 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
Second round, 16 bytes , the original message is encrypted by xxtea, decrypted as the nonce of chacha20, length 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
Stage 2: Bot--->C2, chacha20 encryption
Once Bot receives the key and nonce of chacha20, it sends the message
netstage=4 to C2, this time the message is encrypted using chacha20, the key&nonce is obtained from the previous stage, the number of rounds encrypted is 1.
We can decrypt the above traffic using the following python code that
from Crypto.Cipher import ChaCha20 cha=ChaCha20.new(key=chaKey,nonce=chaNonce) cha.seek(64) tmp=bytes.fromhex('dc23c56943431018b61262481ce5a219da9480930f08714e017edc56bf903d32ac5daeb8314f1bf7e6') rnd3=cha.decrypt(tmp)
The decrypted traffic is shown below, it still has the format of head (7 bytes) + body as described before, where the value of the netstage field of head is 04, which represents the authentication.
Stage 2: C2 ---> Bot, chacha20 encryption
After receiving the authentication message from Bot, C2 also sends a message with
netstage=4 to Bot's data, also using chacha20 encryption, and the key,nonce,round number is the same as that used by Bot.
Using the same code as Bot to decrypt the traffic, we can see that its format is also head+body, and the value of netstage is also 04.
After Bot and C2 send each other the message
netstage=4, the chacha20 key&nonce representing stage 1 is recognized by both parties, and the authentication of each other is completed, and Bot enters the next stage to prepare to go online.
Stage 3: Bot--->C2, 2 rounds, chacha encryption
Bot sends netstage=5 message to C2 to indicate that it is ready to go online, and then reports its own grouping information to C2, these 2 rounds of messages also use chacha20 encryption.
After the above two rounds of data decryption, we can see that the content of the group is exactly the preset
fsdsaD, which means our analysis is correct, so the Bot is successfully online and starts to wait for the execution of the command sent by C2.
0x4: Execute command
Bot successfully online, support the netstage number, as shown in the figure below, the most important is the
netstage = 1 on behalf of the DDoS task, Fodcha reuse a large number of Mirai attack code, a total of
17 kinds of attack methods are supported.
Take the following
(netstage=01) as an example.
The attack instructions are still encrypted using
chacha20, and the decrypted instructions are shown below, which might ring a bell for readers who are familiar with
00000000: 00 00 00 3C 07 01 xx 14 93 01 20 02 00 00 02 01 00000010: BB 01 00 02 00 01
The format and parsing of the above attack instructions are shown in the following table.
|0x00||4||00 00 00 3c||Duration|
|0x05||1||1||Attack Target Cnt|
|0x06||4||xx 14 93 01||Attack Target，xx.20.147.1|
|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)|
When Bot receives the above instruction, it will use the tcp message with a payload of 1 byte to conduct a DDoS attack on the target
xx.20.147.1:443, which corresponds to the actual packet capture traffic.
From some of the OpenNIC C2 constructs, it seems that the author of Fodcha is more hostile to people from some regions.
yellowchinks.geek wearelegal.geek funnyyellowpeople.libre chinksdogeaters.dyn blackpeeps.dyn bladderfull.indy wehateyellow
0x02: Ransom DDoS
Fodcha had the following string attached to the UDP attack command it issued.
send 10 xmr to 49UnJhpvRRxDXJHYczoUEiK3EKCQZorZWaV6HD7axKGQd5xpUQeNp7Xg9RATFpL4u8dzPfAnuMYqs2Kch1soaf5B5mdfJ1b or we will shutdown your business
The corresponding attack traffic is shown below, the wallet address appears to be illegal, perhaps the operators behind Fodcha are experimenting with the attack-as-ransom business model, we will see how it evolve.
Readers are always welcomed to reach us on twitter or email us to netlab[at]360.cn.
v1,v2: folded[.]in fridgexperts[.]cc ICANN C2: forwardchinks[.]com doodleching[.]com cookiemonsterboob[.]com milfsfors3x[.]com OpenNIC C2: yellowchinks.geek yellowchinks.dyn wearelegal.geek tsengtsing.libre techsupporthelpars.oss respectkkk.geek pepperfan.geek peepeepoo.libre obamalover.pirate funnyyellowpeople.libre chinksdogeaters.dyn chinkchink.libre bladderfull.indy blackpeeps.dyn 126.96.36.199 188.8.131.52 184.108.40.206 220.127.116.11 18.104.22.168 22.214.171.124 126.96.36.199 188.8.131.52 184.108.40.206 220.127.116.11 18.104.22.168 22.214.171.124 126.96.36.199 188.8.131.52 184.108.40.206 220.127.116.11 18.104.22.168 22.214.171.124 126.96.36.199 188.8.131.52 184.108.40.206 220.127.116.11 18.104.22.168 22.214.171.124 126.96.36.199 188.8.131.52 184.108.40.206 220.127.116.11 18.104.22.168 22.214.171.124 126.96.36.199 188.8.131.52 184.108.40.206 220.127.116.11 18.104.22.168 22.214.171.124 126.96.36.199 188.8.131.52 184.108.40.206 220.127.116.11 18.104.22.168 22.214.171.124 126.96.36.199 188.8.131.52 184.108.40.206 220.127.116.11 18.104.22.168 22.214.171.124 126.96.36.199 188.8.131.52 184.108.40.206 220.127.116.11 18.104.22.168 22.214.171.124 126.96.36.199 188.8.131.52 184.108.40.206 220.127.116.11 18.104.22.168 22.214.171.124 126.96.36.199 188.8.131.52 184.108.40.206 220.127.116.11 18.104.22.168 22.214.171.124 126.96.36.199 188.8.131.52 184.108.40.206 220.127.116.11 18.104.22.168 22.214.171.124 126.96.36.199 188.8.131.52 184.108.40.206 220.127.116.11 18.104.22.168 22.214.171.124 126.96.36.199 188.8.131.52 184.108.40.206 220.127.116.11 18.104.22.168 22.214.171.124 126.96.36.199 188.8.131.52 184.108.40.206 220.127.116.11 18.104.22.168 22.214.171.124 126.96.36.199 188.8.131.52 184.108.40.206 220.127.116.11
ea7945724837f019507fd613ba3e1da9 899047ddf6f62f07150837aef0c1ebfb 0f781868d4b9203569357b2dbc46ef10