New Threat: B1txor20, A Linux Backdoor Using DNS Tunnel
<!--kg-card-begin: markdown--><h2 id="background">Background</h2>
<p>Since the <strong>Log4J vulnerability</strong> was exposed, we see more and more malware jumped on the wagon, Elknot, Gafgyt, Mirai are all too familiar, on February 9, 2022, 360Netlab's honeypot system captured an unknown ELF file propagating through the Log4J vulnerability. What stands out is that the network traffic generated by this sample triggered a <strong>DNS Tunnel alert</strong> in our system, We decided to take a close look, and indeed, it is a new botnet family, which we named <strong>B1txor20</strong> based on its propagation using the file name &quot;b1t&quot;, the XOR encryption algorithm, and the RC4 algorithm key length of 20 bytes.</p>
<p>In short, B1txor20 is a Backdoor for the Linux platform, which uses DNS Tunnel technology to build C2 communication channels. In addition to the traditional backdoor functions, B1txor20 also has functions such as opening Socket5 proxy and remotely downloading and installing Rootkit.</p>
<p>Another interesting point is that we found that many developed features are not put into use (in IDA, there is no cross-reference); some features have bugs. we presume that the author of B1txor20 will continue to improve and open different features according to different scenarios, so maybe we will meet B1txor20's siblings in the future.</p>
<h2 id="b1txor20overview">B1txor20 Overview</h2>
<p>We have captured a total of four different B1txor20 samples, their functions are almost the same, a total of 15 function numbers are supported, according to these functions, B1txor20 can be characterized as: <strong>using DNS Tunnel to establish C2 channel</strong>, support direct connection and relay, while using <code>ZLIB compression, RC4 encryption, BASE64 encoding</code>to protect the traffic of the backdoor Trojan, mainly targets <code>ARM, X64 CPU</code> architecture of the Linux platform.</p>
<p>The main features currently supported are shown below.</p>
<ol>
<li>SHELL</li>
<li>Proxy</li>
<li>Execute arbitrary commands</li>
<li>Install Rootkit</li>
<li>Upload sensitive information</li>
</ol>
<p>Its basic flowchart is shown below.</p>
<img src="__GHOST_URL__/content/images/2022/03/b1t_net.png"  width="860px" />
<h2 id="reverseanalysis">Reverse Analysis</h2>
<p>We choose the sample on February 09, 2022 as the main object of analysis, and its basic information is shown as follows.</p>
<pre><code>MD5:0a0c43726fd256ad827f4108bdf5e772

ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.18, stripped

Packer:None
</code></pre>
<p>The sample of B1txor20 is dynamically linked, so it is relatively easy to reverse. Simply put, when B1txor20 executes, it will first disguise itself as a [netns] process, run a single instance through the PID file<code>/var/run/.netns.pid</code>, and then use <code>/etc/machine-id</code>, <code>/tmp/.138171241</code> or <code>/dev/urandom</code> to generate the BotID, then decrypt the domain name used for DNS Tunnel and the RC4 secret key used to encrypt the traffic and test the connectivity of the DNS server, and finally use DNS Tunnel to send registration information to C2 and wait for the execution of the commands issued by C2. Here we will not go into details about the regular functions, we will take a look at the DNS Tunnel implementation of the B1txor20.</p>
<h2 id="generatingbotid">Generating Bot ID</h2>
<p>B1txor20 uses the following code snippet to read 32 bytes from <code>/etc/machine-id</code>, or <code>/tmp/.138171241</code>, for generating BotId, and if it fails, a 16 bytes of data will be generated via /dev/urandom and will be written to the previous 2 files.</p>
<img src="__GHOST_URL__/content/images/2022/03/b1t_id.png"  width="860px" />
<p>The following code snippet shows the process of BotId calculation.</p>
<img src="__GHOST_URL__/content/images/2022/03/b1t_calc.png"  width="860px" />
<p>Taking the machine-id value<code>ab3b49d10ec42c38b1093b8ce9ad12af</code>of our VM as an example, the following equivalent python code can be used to calculate the value of BotId as <strong>0x125d</strong>.</p>
<pre><code class="language-python">import struct
id='ab3b49d10ec42c38b1093b8ce9ad12af'
values=struct.unpack(&quot;&lt;16H&quot;,id)
sum=0
for i in values:
    sum ^= i
print hex(sum)
if sum&amp;0xff &lt;0xf:
    sum+=0x10
if sum&gt;&gt;8 &lt; 0xf:
    sum+=0x1000
print hex(sum)   # sum=0x125d

</code></pre>
<h2 id="decryption">Decryption</h2>
<p>B1txor20 decrypts the domain name and RC4 secret key stored in the sample with the following code snippet.</p>
<img src="__GHOST_URL__/content/images/2022/03/b1t_dec.png"  width="860px" />
<p>Its principle is very simple, it is a single-byte xor operation, where xor_key is<code>49 D3 4F A7 A2 BC 4D FA 40 CF A6 32 31 E9 59 A1</code>.</p>
<img src="__GHOST_URL__/content/images/2022/03/b1t_xor.png"  width="860px" />
<p>The decryption process is equivalent to the CyberChef implementation in the following figure, which shows that the domain name is<code>.dns.webserv.systems</code> and the RC4 secret key is <code>EnLgLKHhy20f8A1dX85l</code>.</p>
<img src="__GHOST_URL__/content/images/2022/03/b1t_chef_xor.png"  width="860px" />
<h2 id="measuretheconnectivityofdnsservers">Measure the connectivity of DNS servers</h2>
<p>B1txor20 tests the connectivity of 3 DNS (8.8.8.8:53, 8.8.8.4:53, 194.165.16.24:443) servers with the following code snippet.</p>
<img src="__GHOST_URL__/content/images/2022/03/b1t_dns.png"  width="860px" />
<p>The principle is to use <code>res_mkquery</code> API to build the DNS request message for &quot;google.com&quot;, then send the request via <code>res_send</code>, and as long as it can be sent successfully, the network is considered to be connected to the corresponding DNS server, and they are saved for subsequent use.</p>
<img src="__GHOST_URL__/content/images/2022/03/b1t_test.png"  width="860px" />
<p>The actual traffic generated by Bot and 194.165.16.24 is as follows.</p>
<img src="__GHOST_URL__/content/images/2022/03/b1t_show.png"  width="860px" />
<h2 id="cccommunication">C&amp;C Communication</h2>
<p>When the above preparations are completed, B1txor20 enters the final stage, using DNS Tunnel to establish communication with C2 and wait for the execution of the commands sent by C2.</p>
<img src="__GHOST_URL__/content/images/2022/03/b1t_final.png"  width="860px" />
<p>Generally speaking, the scenario of malware using DNS Tunnel is as follows:</p>
<blockquote>
<p>Bot sends the stolen sensitive information, command execution results, and any other information that needs to be delivered, after hiding it using specific encoding techniques, to C2 as a DNS request; After receiving the request, C2 sends the payload to the Bot side as a response to the DNS request. In this way, Bot and C2 achieve communication with the help of DNS protocol.</p>
</blockquote>
<p>In such a network structure, there are 3 key points:</p>
<p>1:C2 must support the DNS protocol<br>
2: Specific encoding techniques<br>
3: The way DNS requests are sent</p>
<p>The following section will analyze the technical details of B1txor20's communication around these points, in conjunction with the traffic generated by B1txor20 in practice.<br>
<img src="__GHOST_URL__/content/images/2022/03/b1t_packet.png"  width="860px" /></p>
<h2 id="0x01locatingc2">0x01:Locating C2</h2>
<p>Through the traffic in the above figure, we can see that the SLD used by B1txor20 is webserv.systems, and using the DIG command, we can see that this SLD is point to IP 194.165.16.24; and the DNS resolution service is turned on at this IP 194, so we can determine that the C2 of B1txor20 is exactly 194.165.16.24.</p>
<img src="__GHOST_URL__/content/images/2022/03/b1t_dnstxt.png"  width="860px" />
<h2 id="0x02generatetunneldomainname">0x02:Generate Tunnel domain name</h2>
<p>The format of B1txor20's Tunnel domain name is<code>Base64-Like String+.dns.websrv.systems</code>. It is obvious that the front Base64 string is the information sent by Bot to C2, <strong>how is it generated</strong>?</p>
<p>First, the B1txor20 packet has a pre-construction process, which can be seen in the format of<code>0xFF + BotId + 0xFF + Stage + 0xFF + TaskInfo</code>, <strong>0xFF</strong> is used to separate different items, and when the construction is finished, according to different Stage values, different tasks will fill the<code>TaskInfo</code>section accordingly.</p>
<img src="__GHOST_URL__/content/images/2022/03/b1t_pre.png"  width="860px" />
<p>Take the above task as an example, the Stage value is 1. Through the <code>gather_info</code> function, the information of &quot;sysinfo_uptime,uid,hostname&quot; is filled into <code>TaskInfo</code>, and they are separated by<strong>0x0a</strong>.</p>
<img src="__GHOST_URL__/content/images/2022/03/b1t_reg.png"  width="860px" />
<p>When the required information is ready, B1txor20 uses the<strong>process_query</strong>function to further process the above information, which includes three processes: <strong>ZLIB compression, RC4 encryption, and Base64 encoding</strong>.</p>
<img src="__GHOST_URL__/content/images/2022/03/b1t_process.png"  width="860px" />
<p>The secret key used in RC4 encryption is the string &quot;EnLgLKHhy20f8A1dX85l&quot; mentioned in the previous decryption section, and the Alphabet String used in Base64 is <code>ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789^_</code>.</p>
<p>Finally, B1txor20 adds 1 byte of status and 4 bytes of random string before the Base64 string generated above, and then splices it with domain, which is the final domain name to be queried. The value of status is ['0', '1', '2'], 0 means that the current query is truncated, the subsequent query and the current should be spelled into the same; 1 means that when the query is complete.</p>
<img src="__GHOST_URL__/content/images/2022/03/b1t_tun.png"  width="860px" />
<p>Let's take a look at the actual generated query <code>1HQoOKPvBKs8yqO1tTUQkCqGWN9anB4RAGWhnJy8A.dns.webserv.systems</code>, removing the first 5 bytes, and the .dns.webserv.systems part to get <code>KPvBKs8yqO1tTUQkCqGWN9anB4RAGWhnJy8A</code>, then use Base64 decoding, RC4 decryption, ZLIB decompression, you can get the following raw data.</p>
<img src="__GHOST_URL__/content/images/2022/03/b1t_origin.png"  width="860px" />
<p>From the data content and format, it can correspond with our previous description one by one, indicating that our previous analysis is correct.</p>
<pre><code>Botid =0x125d
Stage=1
sysinfo.uptime = 34
uid=30
hostname=debian
</code></pre>
<h2 id="0x3senddnsrequest">0x3:Send DNS request</h2>
<p>When the above domain name construction is complete, B1txor20 generates and sends DNS requests using the RES series API.</p>
<img src="__GHOST_URL__/content/images/2022/03/b1t_senddns.png"  width="860px" />
<p>There are 3 ways to send DNS requests, depending on the previous test of DNS connectivity.</p>
<p>1.Send to public dns (8.8.8.8, 8.8.4.4)<br>
2.Send directly to C2 (194.165.16.24)<br>
3.Send to local dns (nameserver in /etc/resolv.conf)</p>
<p>In this way, it is faster, but less concealed and easy to be detected and traced; in this way, 1 and 3 are more concealed, but a little slower.</p>
<h2 id="0x4processc2payload">0x4:Process C2 payload</h2>
<p>After the Bot sends the DNS request in the above way, it waits for the execution of the C2 instruction, which is stored in the response message of the DNS request in the format of <code>Status(1 byte):Body</code>, where the Body part also uses &quot;ZLIB compression, RC4 encryption, BASE64 encoding &quot; protection method.</p>
<img src="__GHOST_URL__/content/images/2022/03/b1t_recv.png"  width="860px" />
<p>For example, the actual command &quot;1VSE6NZwczNMm2zgaXeLkZro=&quot; is received in the following figure.</p>
<img src="__GHOST_URL__/content/images/2022/03/b1t_cmd.png"  width="860px" />
<p>Body part for &quot;VSE6NZwczNMm2zgaXeLkZro=&quot;, After decoded by Base64, RC4 decryption, you can get the following format of data, and then decompression of the<code>red part</code>, you get the final instruction <code>FF 02 FF 0A FF</code>, you can see that its format and the format generated by the above query is consistent, at this point it can be known that Bot will go to perform 0x02 function, so that Bot's round of interaction with C2 is complete.</p>
<img src="__GHOST_URL__/content/images/2022/03/b1t_after.png"  width="860px" />
<h2 id="ccinstructions">C&amp;C instructions</h2>
<p>B1txor20 supports a total of 14 instructions, and the correspondence between instruction number and function is shown in the following table.</p>
<table>
<thead>
<tr>
<th>Cmd ID</th>
<th>Function</th>
</tr>
</thead>
<tbody>
<tr>
<td>0x1</td>
<td>Beacon/Heartbeat</td>
</tr>
<tr>
<td>0x2</td>
<td>Upload system info</td>
</tr>
<tr>
<td>0x3</td>
<td>Create &quot;/dev/pamd&quot; (unix domain socket) which can get a shell</td>
</tr>
<tr>
<td>0x4</td>
<td>Exec arbitrary system cmd via popen</td>
</tr>
<tr>
<td>0x5</td>
<td>Traffic forwarding</td>
</tr>
<tr>
<td>0x6</td>
<td>Write File</td>
</tr>
<tr>
<td>0x7</td>
<td>Read File</td>
</tr>
<tr>
<td>0x8</td>
<td>Deliver info via &quot;/var/tmp/.unetns&quot;(unix domain socket)，Not used</td>
</tr>
<tr>
<td>0x9</td>
<td>Upload specific info，Not used</td>
</tr>
<tr>
<td>0x10</td>
<td>Stop proxy service</td>
</tr>
<tr>
<td>0x11</td>
<td>Start proxy  service</td>
</tr>
<tr>
<td>0x1a</td>
<td>Create proxy service</td>
</tr>
<tr>
<td>0x21</td>
<td>Reverse shell</td>
</tr>
<tr>
<td>0x50</td>
<td>Upload &quot;/boot/conf- XXX&quot; info，Not used</td>
</tr>
<tr>
<td>0x51</td>
<td>install M3T4M0RPH1N3.ko rootkit</td>
</tr>
</tbody>
</table>
<p>In the table, &quot;Not used&quot; means that this function has the corresponding processing code in the sample, but it is not called. We are not sure if these codes are used for debugging or in other scenarios.</p>
<p>We found that some functions are buggy in their implementation, such as 0x3, which uses the remove function to delete the socket file after bind the domain socket, which makes the socket unconnectable and thus the whole function is useless.</p>
<img src="__GHOST_URL__/content/images/2022/03/b1t_bug.png"  width="860px" />
<h2 id="smallnote">Small note</h2>
<p>We noticed the domain name has been registered for 6 years, which is kind unusual?</p>
<pre><code>webserv.systems	createddate                 2021-02-08 15:13:22
webserv.systems	updateddate                 2021-02-24 22:27:23
webserv.systems	expiresdate                 2027-02-08 15:13:22
</code></pre>
<h2 id="contactus">Contact us</h2>
<p>Readers are always welcomed to reach us on <a href="https://twitter.com/360Netlab">Twitter</a> or email us to netlab at 360 dot cn.</p>
<h2 id="ioc">IOC</h2>
<h3 id="c2">C2</h3>
<pre><code>webserv.systems
194.165.16.24:53
194.165.16.24:443
</code></pre>
<h3 id="scanner">Scanner</h3>
<pre><code>104.244.73.126	Luxembourg|Luxembourg|Unknown	53667|FranTech_Solutions
109.201.133.100	Netherlands|North_Holland|Amsterdam	43350|NForce_Entertainment_B.V.
162.247.74.27	United_States|New_York|New_York_City	4224|The_Calyx_Institute
166.78.48.7	United_States|Texas|Dallas	33070|Rackspace_Hosting
171.25.193.78	Sweden|Stockholm_County|Stockholm	198093|Foreningen_for_digitala_fri-_och_rattigheter
185.100.87.202	Romania|Bucharest|Unknown	200651|Flokinet_Ltd
185.129.62.62	Denmark|Region_Hovedstaden|Copenhagen	57860|Zencurity_ApS
185.220.100.240	Germany|Bavaria|Nuremberg	205100|F3_Netze_e.V.
185.220.100.241	Germany|Bavaria|Nuremberg	205100|F3_Netze_e.V.
185.220.100.242	Germany|Bavaria|Nuremberg	205100|F3_Netze_e.V.
185.220.100.243	Germany|Bavaria|Nuremberg	205100|F3_Netze_e.V.
185.220.100.246	Germany|Bavaria|Nuremberg	205100|F3_Netze_e.V.
185.220.100.249	Germany|Bavaria|Nuremberg	205100|F3_Netze_e.V.
185.220.100.250	Germany|Bavaria|Nuremberg	205100|F3_Netze_e.V.
185.220.100.252	Germany|Bavaria|Nuremberg	205100|F3_Netze_e.V.
185.220.100.254	Germany|Bavaria|Nuremberg	205100|F3_Netze_e.V.
185.220.100.255	Germany|Bavaria|Nuremberg	205100|F3_Netze_e.V.
185.220.101.134	Netherlands|North_Holland|Amsterdam	200052|Feral.io_Ltd
185.220.101.136	Netherlands|North_Holland|Amsterdam	200052|Feral.io_Ltd
185.220.101.140	Netherlands|North_Holland|Amsterdam	200052|Feral.io_Ltd
185.220.101.143	Netherlands|North_Holland|Amsterdam	200052|Feral.io_Ltd
185.220.101.144	Netherlands|North_Holland|Amsterdam	200052|Feral.io_Ltd
185.220.101.151	Netherlands|North_Holland|Amsterdam	200052|Feral.io_Ltd
185.220.101.155	Netherlands|North_Holland|Amsterdam	200052|Feral.io_Ltd
185.220.101.161	Netherlands|North_Holland|Amsterdam	200052|Feral.io_Ltd
185.220.101.162	Netherlands|North_Holland|Amsterdam	200052|Feral.io_Ltd
185.220.101.164	Netherlands|North_Holland|Amsterdam	200052|Feral.io_Ltd
185.220.101.166	Netherlands|North_Holland|Amsterdam	200052|Feral.io_Ltd
185.220.101.168	Netherlands|North_Holland|Amsterdam	200052|Feral.io_Ltd
185.220.101.172	Netherlands|North_Holland|Amsterdam	200052|Feral.io_Ltd
185.220.101.174	Netherlands|North_Holland|Amsterdam	200052|Feral.io_Ltd
185.220.101.176	Netherlands|North_Holland|Amsterdam	200052|Feral.io_Ltd
185.220.101.181	Netherlands|North_Holland|Amsterdam	200052|Feral.io_Ltd
185.220.101.191	Netherlands|North_Holland|Amsterdam	200052|Feral.io_Ltd
185.220.101.34	Netherlands|North_Holland|Amsterdam	200052|Feral.io_Ltd
185.220.101.37	Netherlands|North_Holland|Amsterdam	200052|Feral.io_Ltd
185.220.101.39	Netherlands|North_Holland|Amsterdam	200052|Feral.io_Ltd
185.220.101.40	Netherlands|North_Holland|Amsterdam	200052|Feral.io_Ltd
185.220.101.42	Netherlands|North_Holland|Amsterdam	200052|Feral.io_Ltd
185.220.101.43	Netherlands|North_Holland|Amsterdam	200052|Feral.io_Ltd
185.220.101.46	Netherlands|North_Holland|Amsterdam	200052|Feral.io_Ltd
185.220.101.5	Netherlands|North_Holland|Amsterdam	200052|Feral.io_Ltd
185.220.101.50	Netherlands|North_Holland|Amsterdam	200052|Feral.io_Ltd
185.220.101.51	Netherlands|North_Holland|Amsterdam	200052|Feral.io_Ltd
185.220.101.53	Netherlands|North_Holland|Amsterdam	200052|Feral.io_Ltd
185.220.101.54	Netherlands|North_Holland|Amsterdam	200052|Feral.io_Ltd
185.220.101.56	Netherlands|North_Holland|Amsterdam	200052|Feral.io_Ltd
185.220.101.57	Netherlands|North_Holland|Amsterdam	200052|Feral.io_Ltd
185.220.101.61	Netherlands|North_Holland|Amsterdam	200052|Feral.io_Ltd
185.56.80.65	Netherlands|South_Holland|Capelle_aan_den_IJssel	43350|NForce_Entertainment_B.V.
193.218.118.158	Ukraine|Kiev|Unknown	None;
194.32.107.159	Romania|Romania|Unknown	None;
194.32.107.187	Romania|Romania|Unknown	None;
194.88.143.66	Italy|Lombardy|Metropolitan_City_of_Milan	49367|Seflow_S.N.C._Di_Marco_Brame'_&amp;_C.
199.195.250.77	United_States|New_York|New_York_City	53667|FranTech_Solutions
23.129.64.216	United_States|Washington|Seattle	396507|Emerald_Onion
23.154.177.4	North_America_Regions|North_America_Regions|Unknown	None;
45.13.104.179	France|Ile-de-France|Paris	57199|MilkyWan
45.154.255.147	Sweden|Stockholm_County|Stockholm	41281|KeFF_Networks_Ltd
45.61.185.90	United_States|United_States|Unknown	8100|QuadraNet_Enterprises_LLC
46.166.139.111	Netherlands|South_Holland|Capelle_aan_den_IJssel	43350|NForce_Entertainment_B.V.
5.2.69.50	Netherlands|Flevoland|Dronten	60404|Liteserver_Holding_B.V.
51.15.43.205	Netherlands|North_Holland|Haarlem	12876|Online_S.a.s.
62.102.148.68	Sweden|Stockholm_County|Akersberga	51815|IP-Only_Networks_AB
62.102.148.69	Sweden|Stockholm_County|Akersberga	51815|IP-Only_Networks_AB
81.17.18.62	Switzerland|Canton_of_Ticino|Unknown	51852|Private_Layer_INC
</code></pre>
<h3 id="downloader">Downloader</h3>
<pre><code>hxxp://179.60.150.23:8000/xExportObject.class
ldap://179.60.150.23:1389/o=tomcat
hxxp://194.165.16.24:8229/b1t_1t.sh
hxxp://194.165.16.24:8228/b1t
hxxp://194.165.16.24:8228/b1t
hxxp://194.165.16.24:8228/_run.sh
hxxp://194.165.16.24:8228/run.sh
hxxp://194.165.16.24:8228/share.sh
hxxp://194.165.16.24:8228/b1t
hxxp://194.165.16.24:8228/run.sh
hxxp://194.165.16.24:8228/run.sh
hxxp://194.165.16.24:8229/b4d4b1t.elf
</code></pre>
<h3 id="samplemd5">Sample MD5</h3>
<pre><code>027d74534a32ba27f225fff6ee7a755f
0a0c43726fd256ad827f4108bdf5e772
24c49e4c75c6662365e10bbaeaeecb04
2e5724e968f91faaf156c48ec879bb40
3192e913ed0138b2de32c5e95146a24a
40024288c0d230c0b8ad86075bd7c678
43fcb5f22a53a88e726ebef46095cd6b
59690bd935184f2ce4b7de0a60e23f57
5f77c32c37ae7d25e927d91eb3b61c87
6b42a9f10db8b11a15006abced212fa4
6c05637c29b347c28d05b937e670c81e
7ef9d37e18b48de4b26e5d188a383ec8
7f4e74e15fafaf3f8b79254558019d7f
989dd7aa17244da78309d441d265613a
dd4b6e2750f86f2630e3aea418d294c0
e82135951c3d485b7133b9673194a79e
fd84b2f06f90940cb920e20ad4a30a63

</code></pre>
<!--kg-card-end: markdown-->
Background


Since the Log4J vulnerability was exposed, we see more and more malware jumped on the wagon, Elknot, Gafgyt, Mirai are all too familiar, on February 9, 2022, 360Netlab's honeypot system captured an unknown ELF file propagating through the Log4J vulnerability. What stands out is that the network traffic generated by this sample triggered a DNS Tunnel alert in our system, We decided to take a close look, and indeed, it is a new botnet family, which we named B1txor20 based on its propagation using the file name "b1t", the XOR encryption algorithm, and the RC4 algorithm key length of 20 bytes.


In short, B1txor20 is a Backdoor for the Linux platform, which uses DNS Tunnel technology to build C2 communication channels. In addition to the traditional backdoor functions, B1txor20 also has functions such as opening Socket5 proxy and remotely downloading and installing Rootkit.


Another interesting point is that we found that many developed features are not put into use (in IDA, there is no cross-reference); some features have bugs. we presume that the author of B1txor20 will continue to improve and open different features according to different scenarios, so maybe we will meet B1txor20's siblings in the future.



B1txor20 Overview


We have captured a total of four different B1txor20 samples, their functions are almost the same, a total of 15 function numbers are supported, according to these functions, B1txor20 can be characterized as: using DNS Tunnel to establish C2 channel, support direct connection and relay, while using ZLIB compression, RC4 encryption, BASE64 encodingto protect the traffic of the backdoor Trojan, mainly targets ARM, X64 CPU architecture of the Linux platform.


The main features currently supported are shown below.


 1. SHELL
 2. Proxy
 3. Execute arbitrary commands
 4. Install Rootkit
 5. Upload sensitive information


Its basic flowchart is shown below.




Reverse Analysis


We choose the sample on February 09, 2022 as the main object of analysis, and its basic information is shown as follows.


MD5:0a0c43726fd256ad827f4108bdf5e772

ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.18, stripped

Packer:None



The sample of B1txor20 is dynamically linked, so it is relatively easy to reverse. Simply put, when B1txor20 executes, it will first disguise itself as a [netns] process, run a single instance through the PID file/var/run/.netns.pid, and then use /etc/machine-id, /tmp/.138171241 or /dev/urandom to generate the BotID, then decrypt the domain name used for DNS Tunnel and the RC4 secret key used to encrypt the traffic and test the connectivity of the DNS server, and finally use DNS Tunnel to send registration information to C2 and wait for the execution of the commands issued by C2. Here we will not go into details about the regular functions, we will take a look at the DNS Tunnel implementation of the B1txor20.



Generating Bot ID


B1txor20 uses the following code snippet to read 32 bytes from /etc/machine-id, or /tmp/.138171241, for generating BotId, and if it fails, a 16 bytes of data will be generated via /dev/urandom and will be written to the previous 2 files.



The following code snippet shows the process of BotId calculation.



Taking the machine-id valueab3b49d10ec42c38b1093b8ce9ad12afof our VM as an example, the following equivalent python code can be used to calculate the value of BotId as 0x125d.


import struct
id='ab3b49d10ec42c38b1093b8ce9ad12af'
values=struct.unpack("<16H",id)
sum=0
for i in values:
    sum ^= i
print hex(sum)
if sum&0xff <0xf:
    sum+=0x10
if sum>>8 < 0xf:
    sum+=0x1000
print hex(sum)   # sum=0x125d





Decryption


B1txor20 decrypts the domain name and RC4 secret key stored in the sample with the following code snippet.



Its principle is very simple, it is a single-byte xor operation, where xor_key is49 D3 4F A7 A2 BC 4D FA 40 CF A6 32 31 E9 59 A1.



The decryption process is equivalent to the CyberChef implementation in the following figure, which shows that the domain name is.dns.webserv.systems and the RC4 secret key is EnLgLKHhy20f8A1dX85l.




Measure the connectivity of DNS servers


B1txor20 tests the connectivity of 3 DNS (8.8.8.8:53, 8.8.8.4:53, 194.165.16.24:443) servers with the following code snippet.



The principle is to use res_mkquery API to build the DNS request message for "google.com", then send the request via res_send, and as long as it can be sent successfully, the network is considered to be connected to the corresponding DNS server, and they are saved for subsequent use.



The actual traffic generated by Bot and 194.165.16.24 is as follows.




C&C Communication


When the above preparations are completed, B1txor20 enters the final stage, using DNS Tunnel to establish communication with C2 and wait for the execution of the commands sent by C2.



Generally speaking, the scenario of malware using DNS Tunnel is as follows:





Bot sends the stolen sensitive information, command execution results, and any other information that needs to be delivered, after hiding it using specific encoding techniques, to C2 as a DNS request; After receiving the request, C2 sends the payload to the Bot side as a response to the DNS request. In this way, Bot and C2 achieve communication with the help of DNS protocol.



In such a network structure, there are 3 key points:


1:C2 must support the DNS protocol

2: Specific encoding techniques

3: The way DNS requests are sent


The following section will analyze the technical details of B1txor20's communication around these points, in conjunction with the traffic generated by B1txor20 in practice.





0x01:Locating C2


Through the traffic in the above figure, we can see that the SLD used by B1txor20 is webserv.systems, and using the DIG command, we can see that this SLD is point to IP 194.165.16.24; and the DNS resolution service is turned on at this IP 194, so we can determine that the C2 of B1txor20 is exactly 194.165.16.24.




0x02:Generate Tunnel domain name


The format of B1txor20's Tunnel domain name isBase64-Like String+.dns.websrv.systems. It is obvious that the front Base64 string is the information sent by Bot to C2, how is it generated?


First, the B1txor20 packet has a pre-construction process, which can be seen in the format of0xFF + BotId + 0xFF + Stage + 0xFF + TaskInfo, 0xFF is used to separate different items, and when the construction is finished, according to different Stage values, different tasks will fill theTaskInfosection accordingly.



Take the above task as an example, the Stage value is 1. Through the gather_info function, the information of "sysinfo_uptime,uid,hostname" is filled into TaskInfo, and they are separated by0x0a.



When the required information is ready, B1txor20 uses theprocess_queryfunction to further process the above information, which includes three processes: ZLIB compression, RC4 encryption, and Base64 encoding.



The secret key used in RC4 encryption is the string "EnLgLKHhy20f8A1dX85l" mentioned in the previous decryption section, and the Alphabet String used in Base64 is ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789^_.


Finally, B1txor20 adds 1 byte of status and 4 bytes of random string before the Base64 string generated above, and then splices it with domain, which is the final domain name to be queried. The value of status is ['0', '1', '2'], 0 means that the current query is truncated, the subsequent query and the current should be spelled into the same; 1 means that when the query is complete.



Let's take a look at the actual generated query 1HQoOKPvBKs8yqO1tTUQkCqGWN9anB4RAGWhnJy8A.dns.webserv.systems, removing the first 5 bytes, and the .dns.webserv.systems part to get KPvBKs8yqO1tTUQkCqGWN9anB4RAGWhnJy8A, then use Base64 decoding, RC4 decryption, ZLIB decompression, you can get the following raw data.



From the data content and format, it can correspond with our previous description one by one, indicating that our previous analysis is correct.


Botid =0x125d
Stage=1
sysinfo.uptime = 34
uid=30
hostname=debian




0x3:Send DNS request


When the above domain name construction is complete, B1txor20 generates and sends DNS requests using the RES series API.



There are 3 ways to send DNS requests, depending on the previous test of DNS connectivity.


1.Send to public dns (8.8.8.8, 8.8.4.4)

2.Send directly to C2 (194.165.16.24)

3.Send to local dns (nameserver in /etc/resolv.conf)


In this way, it is faster, but less concealed and easy to be detected and traced; in this way, 1 and 3 are more concealed, but a little slower.



0x4:Process C2 payload


After the Bot sends the DNS request in the above way, it waits for the execution of the C2 instruction, which is stored in the response message of the DNS request in the format of Status(1 byte):Body, where the Body part also uses "ZLIB compression, RC4 encryption, BASE64 encoding " protection method.



For example, the actual command "1VSE6NZwczNMm2zgaXeLkZro=" is received in the following figure.



Body part for "VSE6NZwczNMm2zgaXeLkZro=", After decoded by Base64, RC4 decryption, you can get the following format of data, and then decompression of thered part, you get the final instruction FF 02 FF 0A FF, you can see that its format and the format generated by the above query is consistent, at this point it can be known that Bot will go to perform 0x02 function, so that Bot's round of interaction with C2 is complete.




C&C instructions


B1txor20 supports a total of 14 instructions, and the correspondence between instruction number and function is shown in the following table.





Cmd ID
Function




0x1
Beacon/Heartbeat


0x2
Upload system info


0x3
Create "/dev/pamd" (unix domain socket) which can get a shell


0x4
Exec arbitrary system cmd via popen


0x5
Traffic forwarding


0x6
Write File


0x7
Read File


0x8
Deliver info via "/var/tmp/.unetns"(unix domain socket)，Not used


0x9
Upload specific info，Not used


0x10
Stop proxy service


0x11
Start proxy service


0x1a
Create proxy service


0x21
Reverse shell


0x50
Upload "/boot/conf- XXX" info，Not used


0x51
install M3T4M0RPH1N3.ko rootkit





In the table, "Not used" means that this function has the corresponding processing code in the sample, but it is not called. We are not sure if these codes are used for debugging or in other scenarios.


We found that some functions are buggy in their implementation, such as 0x3, which uses the remove function to delete the socket file after bind the domain socket, which makes the socket unconnectable and thus the whole function is useless.




Small note


We noticed the domain name has been registered for 6 years, which is kind unusual?


webserv.systems	createddate                 2021-02-08 15:13:22
webserv.systems	updateddate                 2021-02-24 22:27:23
webserv.systems	expiresdate                 2027-02-08 15:13:22




Contact us


Readers are always welcomed to reach us on Twitter or email us to netlab at 360 dot cn.



IOC



C2


webserv.systems
194.165.16.24:53
194.165.16.24:443




Scanner


104.244.73.126	Luxembourg|Luxembourg|Unknown	53667|FranTech_Solutions
109.201.133.100	Netherlands|North_Holland|Amsterdam	43350|NForce_Entertainment_B.V.
162.247.74.27	United_States|New_York|New_York_City	4224|The_Calyx_Institute
166.78.48.7	United_States|Texas|Dallas	33070|Rackspace_Hosting
171.25.193.78	Sweden|Stockholm_County|Stockholm	198093|Foreningen_for_digitala_fri-_och_rattigheter
185.100.87.202	Romania|Bucharest|Unknown	200651|Flokinet_Ltd
185.129.62.62	Denmark|Region_Hovedstaden|Copenhagen	57860|Zencurity_ApS
185.220.100.240	Germany|Bavaria|Nuremberg	205100|F3_Netze_e.V.
185.220.100.241	Germany|Bavaria|Nuremberg	205100|F3_Netze_e.V.
185.220.100.242	Germany|Bavaria|Nuremberg	205100|F3_Netze_e.V.
185.220.100.243	Germany|Bavaria|Nuremberg	205100|F3_Netze_e.V.
185.220.100.246	Germany|Bavaria|Nuremberg	205100|F3_Netze_e.V.
185.220.100.249	Germany|Bavaria|Nuremberg	205100|F3_Netze_e.V.
185.220.100.250	Germany|Bavaria|Nuremberg	205100|F3_Netze_e.V.
185.220.100.252	Germany|Bavaria|Nuremberg	205100|F3_Netze_e.V.
185.220.100.254	Germany|Bavaria|Nuremberg	205100|F3_Netze_e.V.
185.220.100.255	Germany|Bavaria|Nuremberg	205100|F3_Netze_e.V.
185.220.101.134	Netherlands|North_Holland|Amsterdam	200052|Feral.io_Ltd
185.220.101.136	Netherlands|North_Holland|Amsterdam	200052|Feral.io_Ltd
185.220.101.140	Netherlands|North_Holland|Amsterdam	200052|Feral.io_Ltd
185.220.101.143	Netherlands|North_Holland|Amsterdam	200052|Feral.io_Ltd
185.220.101.144	Netherlands|North_Holland|Amsterdam	200052|Feral.io_Ltd
185.220.101.151	Netherlands|North_Holland|Amsterdam	200052|Feral.io_Ltd
185.220.101.155	Netherlands|North_Holland|Amsterdam	200052|Feral.io_Ltd
185.220.101.161	Netherlands|North_Holland|Amsterdam	200052|Feral.io_Ltd
185.220.101.162	Netherlands|North_Holland|Amsterdam	200052|Feral.io_Ltd
185.220.101.164	Netherlands|North_Holland|Amsterdam	200052|Feral.io_Ltd
185.220.101.166	Netherlands|North_Holland|Amsterdam	200052|Feral.io_Ltd
185.220.101.168	Netherlands|North_Holland|Amsterdam	200052|Feral.io_Ltd
185.220.101.172	Netherlands|North_Holland|Amsterdam	200052|Feral.io_Ltd
185.220.101.174	Netherlands|North_Holland|Amsterdam	200052|Feral.io_Ltd
185.220.101.176	Netherlands|North_Holland|Amsterdam	200052|Feral.io_Ltd
185.220.101.181	Netherlands|North_Holland|Amsterdam	200052|Feral.io_Ltd
185.220.101.191	Netherlands|North_Holland|Amsterdam	200052|Feral.io_Ltd
185.220.101.34	Netherlands|North_Holland|Amsterdam	200052|Feral.io_Ltd
185.220.101.37	Netherlands|North_Holland|Amsterdam	200052|Feral.io_Ltd
185.220.101.39	Netherlands|North_Holland|Amsterdam	200052|Feral.io_Ltd
185.220.101.40	Netherlands|North_Holland|Amsterdam	200052|Feral.io_Ltd
185.220.101.42	Netherlands|North_Holland|Amsterdam	200052|Feral.io_Ltd
185.220.101.43	Netherlands|North_Holland|Amsterdam	200052|Feral.io_Ltd
185.220.101.46	Netherlands|North_Holland|Amsterdam	200052|Feral.io_Ltd
185.220.101.5	Netherlands|North_Holland|Amsterdam	200052|Feral.io_Ltd
185.220.101.50	Netherlands|North_Holland|Amsterdam	200052|Feral.io_Ltd
185.220.101.51	Netherlands|North_Holland|Amsterdam	200052|Feral.io_Ltd
185.220.101.53	Netherlands|North_Holland|Amsterdam	200052|Feral.io_Ltd
185.220.101.54	Netherlands|North_Holland|Amsterdam	200052|Feral.io_Ltd
185.220.101.56	Netherlands|North_Holland|Amsterdam	200052|Feral.io_Ltd
185.220.101.57	Netherlands|North_Holland|Amsterdam	200052|Feral.io_Ltd
185.220.101.61	Netherlands|North_Holland|Amsterdam	200052|Feral.io_Ltd
185.56.80.65	Netherlands|South_Holland|Capelle_aan_den_IJssel	43350|NForce_Entertainment_B.V.
193.218.118.158	Ukraine|Kiev|Unknown	None;
194.32.107.159	Romania|Romania|Unknown	None;
194.32.107.187	Romania|Romania|Unknown	None;
194.88.143.66	Italy|Lombardy|Metropolitan_City_of_Milan	49367|Seflow_S.N.C._Di_Marco_Brame'_&_C.
199.195.250.77	United_States|New_York|New_York_City	53667|FranTech_Solutions
23.129.64.216	United_States|Washington|Seattle	396507|Emerald_Onion
23.154.177.4	North_America_Regions|North_America_Regions|Unknown	None;
45.13.104.179	France|Ile-de-France|Paris	57199|MilkyWan
45.154.255.147	Sweden|Stockholm_County|Stockholm	41281|KeFF_Networks_Ltd
45.61.185.90	United_States|United_States|Unknown	8100|QuadraNet_Enterprises_LLC
46.166.139.111	Netherlands|South_Holland|Capelle_aan_den_IJssel	43350|NForce_Entertainment_B.V.
5.2.69.50	Netherlands|Flevoland|Dronten	60404|Liteserver_Holding_B.V.
51.15.43.205	Netherlands|North_Holland|Haarlem	12876|Online_S.a.s.
62.102.148.68	Sweden|Stockholm_County|Akersberga	51815|IP-Only_Networks_AB
62.102.148.69	Sweden|Stockholm_County|Akersberga	51815|IP-Only_Networks_AB
81.17.18.62	Switzerland|Canton_of_Ticino|Unknown	51852|Private_Layer_INC




Downloader


hxxp://179.60.150.23:8000/xExportObject.class
ldap://179.60.150.23:1389/o=tomcat
hxxp://194.165.16.24:8229/b1t_1t.sh
hxxp://194.165.16.24:8228/b1t
hxxp://194.165.16.24:8228/b1t
hxxp://194.165.16.24:8228/_run.sh
hxxp://194.165.16.24:8228/run.sh
hxxp://194.165.16.24:8228/share.sh
hxxp://194.165.16.24:8228/b1t
hxxp://194.165.16.24:8228/run.sh
hxxp://194.165.16.24:8228/run.sh
hxxp://194.165.16.24:8229/b4d4b1t.elf




Sample MD5


027d74534a32ba27f225fff6ee7a755f
0a0c43726fd256ad827f4108bdf5e772
24c49e4c75c6662365e10bbaeaeecb04
2e5724e968f91faaf156c48ec879bb40
3192e913ed0138b2de32c5e95146a24a
40024288c0d230c0b8ad86075bd7c678
43fcb5f22a53a88e726ebef46095cd6b
59690bd935184f2ce4b7de0a60e23f57
5f77c32c37ae7d25e927d91eb3b61c87
6b42a9f10db8b11a15006abced212fa4
6c05637c29b347c28d05b937e670c81e
7ef9d37e18b48de4b26e5d188a383ec8
7f4e74e15fafaf3f8b79254558019d7f
989dd7aa17244da78309d441d265613a
dd4b6e2750f86f2630e3aea418d294c0
e82135951c3d485b7133b9673194a79e
fd84b2f06f90940cb920e20ad4a30a63



{"version":"0.3.1","atoms":[],"cards":[["markdown",{"markdown":"## Background\nSince the **Log4J vulnerability** was exposed, we see more and more malware jumped on the wagon, Elknot, Gafgyt, Mirai are all too familiar, on February 9, 2022, 360Netlab's honeypot system captured an unknown ELF file propagating through the Log4J vulnerability. What stands out is that the network traffic generated by this sample triggered a **DNS Tunnel alert** in our system, We decided to take a close look, and indeed, it is a new botnet family, which we named **B1txor20** based on its propagation using the file name \"b1t\", the XOR encryption algorithm, and the RC4 algorithm key length of 20 bytes.\n\nIn short, B1txor20 is a Backdoor for the Linux platform, which uses DNS Tunnel technology to build C2 communication channels. In addition to the traditional backdoor functions, B1txor20 also has functions such as opening Socket5 proxy and remotely downloading and installing Rootkit.\n\n\nAnother interesting point is that we found that many developed features are not put into use (in IDA, there is no cross-reference); some features have bugs. we presume that the author of B1txor20 will continue to improve and open different features according to different scenarios, so maybe we will meet B1txor20's siblings in the future.\n\n\n## B1txor20 Overview\nWe have captured a total of four different B1txor20 samples, their functions are almost the same, a total of 15 function numbers are supported, according to these functions, B1txor20 can be characterized as: **using DNS Tunnel to establish C2 channel**, support direct connection and relay, while using ```ZLIB compression, RC4 encryption, BASE64 encoding```to protect the traffic of the backdoor Trojan, mainly targets ``ARM, X64 CPU`` architecture of the Linux platform.\n\nThe main features currently supported are shown below.\n\n1. SHELL\n2. Proxy\n3. Execute arbitrary commands\n4. Install Rootkit\n5. Upload sensitive information\n\nIts basic flowchart is shown below.\n\n<img src=\"__GHOST_URL__/content/images/2022/03/b1t_net.png\"  width=\"860px\" />\n\n## Reverse Analysis\nWe choose the sample on February 09, 2022 as the main object of analysis, and its basic information is shown as follows.\n\n```\nMD5:0a0c43726fd256ad827f4108bdf5e772\n\nELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.18, stripped\n\nPacker:None\n```\n\nThe sample of B1txor20 is dynamically linked, so it is relatively easy to reverse. Simply put, when B1txor20 executes, it will first disguise itself as a [netns] process, run a single instance through the PID file``/var/run/.netns.pid``, and then use ``/etc/machine-id``, ``/tmp/.138171241`` or ``/dev/urandom`` to generate the BotID, then decrypt the domain name used for DNS Tunnel and the RC4 secret key used to encrypt the traffic and test the connectivity of the DNS server, and finally use DNS Tunnel to send registration information to C2 and wait for the execution of the commands issued by C2. Here we will not go into details about the regular functions, we will take a look at the DNS Tunnel implementation of the B1txor20.\n\n## Generating Bot ID\n\nB1txor20 uses the following code snippet to read 32 bytes from ``/etc/machine-id``, or ``/tmp/.138171241``, for generating BotId, and if it fails, a 16 bytes of data will be generated via /dev/urandom and will be written to the previous 2 files.\n\n<img src=\"__GHOST_URL__/content/images/2022/03/b1t_id.png\"  width=\"860px\" />\n\n\n\nThe following code snippet shows the process of BotId calculation.\n\n<img src=\"__GHOST_URL__/content/images/2022/03/b1t_calc.png\"  width=\"860px\" />\n\n\nTaking the machine-id value``ab3b49d10ec42c38b1093b8ce9ad12af``of our VM as an example, the following equivalent python code can be used to calculate the value of BotId as **0x125d**.\n\n```python\nimport struct\nid='ab3b49d10ec42c38b1093b8ce9ad12af'\nvalues=struct.unpack(\"<16H\",id)\nsum=0\nfor i in values:\n    sum ^= i\nprint hex(sum)\nif sum&0xff <0xf:\n    sum+=0x10\nif sum>>8 < 0xf:\n    sum+=0x1000\nprint hex(sum)   # sum=0x125d\n\n```\n\n## Decryption\nB1txor20 decrypts the domain name and RC4 secret key stored in the sample with the following code snippet.\n\n<img src=\"__GHOST_URL__/content/images/2022/03/b1t_dec.png\"  width=\"860px\" />\n\nIts principle is very simple, it is a single-byte xor operation, where xor_key is```49 D3 4F A7 A2 BC 4D FA 40 CF A6 32 31 E9 59 A1```.\n\n<img src=\"__GHOST_URL__/content/images/2022/03/b1t_xor.png\"  width=\"860px\" />\n\nThe decryption process is equivalent to the CyberChef implementation in the following figure, which shows that the domain name is``.dns.webserv.systems`` and the RC4 secret key is ``EnLgLKHhy20f8A1dX85l``.\n\n<img src=\"__GHOST_URL__/content/images/2022/03/b1t_chef_xor.png\"  width=\"860px\" />\n\n## Measure the connectivity of DNS servers\nB1txor20 tests the connectivity of 3 DNS (8.8.8.8:53, 8.8.8.4:53, 194.165.16.24:443) servers with the following code snippet.\n\n<img src=\"__GHOST_URL__/content/images/2022/03/b1t_dns.png\"  width=\"860px\" />\n\nThe principle is to use ``res_mkquery`` API to build the DNS request message for \"google.com\", then send the request via ``res_send``, and as long as it can be sent successfully, the network is considered to be connected to the corresponding DNS server, and they are saved for subsequent use.\n\n<img src=\"__GHOST_URL__/content/images/2022/03/b1t_test.png\"  width=\"860px\" />\n\nThe actual traffic generated by Bot and 194.165.16.24 is as follows.\n\n<img src=\"__GHOST_URL__/content/images/2022/03/b1t_show.png\"  width=\"860px\" />\n\n## C&C Communication\nWhen the above preparations are completed, B1txor20 enters the final stage, using DNS Tunnel to establish communication with C2 and wait for the execution of the commands sent by C2.\n\n<img src=\"__GHOST_URL__/content/images/2022/03/b1t_final.png\"  width=\"860px\" />\n\nGenerally speaking, the scenario of malware using DNS Tunnel is as follows: \n>Bot sends the stolen sensitive information, command execution results, and any other information that needs to be delivered, after hiding it using specific encoding techniques, to C2 as a DNS request; After receiving the request, C2 sends the payload to the Bot side as a response to the DNS request. In this way, Bot and C2 achieve communication with the help of DNS protocol.\n\nIn such a network structure, there are 3 key points:\n\n1:C2 must support the DNS protocol\n2: Specific encoding techniques\n3: The way DNS requests are sent\n\nThe following section will analyze the technical details of B1txor20's communication around these points, in conjunction with the traffic generated by B1txor20 in practice.\n<img src=\"__GHOST_URL__/content/images/2022/03/b1t_packet.png\"  width=\"860px\" />\n\n## 0x01:Locating C2\nThrough the traffic in the above figure, we can see that the SLD used by B1txor20 is webserv.systems, and using the DIG command, we can see that this SLD is point to IP 194.165.16.24; and the DNS resolution service is turned on at this IP 194, so we can determine that the C2 of B1txor20 is exactly 194.165.16.24.\n\n<img src=\"__GHOST_URL__/content/images/2022/03/b1t_dnstxt.png\"  width=\"860px\" />\n\n## 0x02:Generate Tunnel domain name\nThe format of B1txor20's Tunnel domain name is```Base64-Like String+.dns.websrv.systems```. It is obvious that the front Base64 string is the information sent by Bot to C2, **how is it generated**?\n\nFirst, the B1txor20 packet has a pre-construction process, which can be seen in the format of``0xFF + BotId + 0xFF + Stage + 0xFF + TaskInfo``, **0xFF** is used to separate different items, and when the construction is finished, according to different Stage values, different tasks will fill the``TaskInfo``section accordingly. \n\n<img src=\"__GHOST_URL__/content/images/2022/03/b1t_pre.png\"  width=\"860px\" />\n\nTake the above task as an example, the Stage value is 1. Through the ``gather_info`` function, the information of \"sysinfo_uptime,uid,hostname\" is filled into ``TaskInfo``, and they are separated by**0x0a**.\n\n<img src=\"__GHOST_URL__/content/images/2022/03/b1t_reg.png\"  width=\"860px\" />\n\nWhen the required information is ready, B1txor20 uses the**process_query**function to further process the above information, which includes three processes: **ZLIB compression, RC4 encryption, and Base64 encoding**.\n\n<img src=\"__GHOST_URL__/content/images/2022/03/b1t_process.png\"  width=\"860px\" />\n\nThe secret key used in RC4 encryption is the string \"EnLgLKHhy20f8A1dX85l\" mentioned in the previous decryption section, and the Alphabet String used in Base64 is ``ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789^_``.\n\nFinally, B1txor20 adds 1 byte of status and 4 bytes of random string before the Base64 string generated above, and then splices it with domain, which is the final domain name to be queried. The value of status is ['0', '1', '2'], 0 means that the current query is truncated, the subsequent query and the current should be spelled into the same; 1 means that when the query is complete.\n\n<img src=\"__GHOST_URL__/content/images/2022/03/b1t_tun.png\"  width=\"860px\" />\n\nLet's take a look at the actual generated query ```1HQoOKPvBKs8yqO1tTUQkCqGWN9anB4RAGWhnJy8A.dns.webserv.systems```, removing the first 5 bytes, and the .dns.webserv.systems part to get ``KPvBKs8yqO1tTUQkCqGWN9anB4RAGWhnJy8A``, then use Base64 decoding, RC4 decryption, ZLIB decompression, you can get the following raw data.\n\n<img src=\"__GHOST_URL__/content/images/2022/03/b1t_origin.png\"  width=\"860px\" />\n\nFrom the data content and format, it can correspond with our previous description one by one, indicating that our previous analysis is correct.\n\n```\nBotid =0x125d\nStage=1\nsysinfo.uptime = 34\nuid=30\nhostname=debian\n```\n\n\n## 0x3:Send DNS request\n\nWhen the above domain name construction is complete, B1txor20 generates and sends DNS requests using the RES series API.\n\n<img src=\"__GHOST_URL__/content/images/2022/03/b1t_senddns.png\"  width=\"860px\" />\n\nThere are 3 ways to send DNS requests, depending on the previous test of DNS connectivity.\n\n1.Send to public dns (8.8.8.8, 8.8.4.4)\n2.Send directly to C2 (194.165.16.24)\n3.Send to local dns (nameserver in /etc/resolv.conf)\n\n\nIn this way, it is faster, but less concealed and easy to be detected and traced; in this way, 1 and 3 are more concealed, but a little slower.\n\n## 0x4:Process C2 payload\nAfter the Bot sends the DNS request in the above way, it waits for the execution of the C2 instruction, which is stored in the response message of the DNS request in the format of ```Status(1 byte):Body```, where the Body part also uses \"ZLIB compression, RC4 encryption, BASE64 encoding \" protection method.\n\n<img src=\"__GHOST_URL__/content/images/2022/03/b1t_recv.png\"  width=\"860px\" />\n\nFor example, the actual command \"1VSE6NZwczNMm2zgaXeLkZro=\" is received in the following figure.\n\n<img src=\"__GHOST_URL__/content/images/2022/03/b1t_cmd.png\"  width=\"860px\" />\n\nBody part for \"VSE6NZwczNMm2zgaXeLkZro=\", After decoded by Base64, RC4 decryption, you can get the following format of data, and then decompression of the``red part``, you get the final instruction ``FF 02 FF 0A FF``, you can see that its format and the format generated by the above query is consistent, at this point it can be known that Bot will go to perform 0x02 function, so that Bot's round of interaction with C2 is complete.\n\n<img src=\"__GHOST_URL__/content/images/2022/03/b1t_after.png\"  width=\"860px\" />\n\n## C&C instructions\nB1txor20 supports a total of 14 instructions, and the correspondence between instruction number and function is shown in the following table.\n\n| Cmd ID | Function                                                     |\n| ------ | ------------------------------------------------------------ |\n| 0x1    | Beacon/Heartbeat                                             |\n| 0x2    | Upload system info                                           |\n| 0x3    | Create \"/dev/pamd\" (unix domain socket) which can get a shell |\n| 0x4    | Exec arbitrary system cmd via popen                          |\n| 0x5    | Traffic forwarding                                           |\n| 0x6    | Write File                                                   |\n| 0x7    | Read File                                                    |\n| 0x8    | Deliver info via \"/var/tmp/.unetns\"(unix domain socket)，Not used |\n| 0x9    | Upload specific info，Not used                               |\n| 0x10   | Stop proxy service                                           |\n| 0x11   | Start proxy  service                                         |\n| 0x1a   | Create proxy service                                         |\n| 0x21   | Reverse shell                                         |\n| 0x50   | Upload \"/boot/conf- XXX\" info，Not used                      |\n| 0x51   | install M3T4M0RPH1N3.ko rootkit                              |\n\nIn the table, \"Not used\" means that this function has the corresponding processing code in the sample, but it is not called. We are not sure if these codes are used for debugging or in other scenarios.\n\nWe found that some functions are buggy in their implementation, such as 0x3, which uses the remove function to delete the socket file after bind the domain socket, which makes the socket unconnectable and thus the whole function is useless.\n\n<img src=\"__GHOST_URL__/content/images/2022/03/b1t_bug.png\"  width=\"860px\" />\n\n## Small note\nWe noticed the domain name has been registered for 6 years, which is kind unusual?\n```\nwebserv.systems\tcreateddate                 2021-02-08 15:13:22\nwebserv.systems\tupdateddate                 2021-02-24 22:27:23\nwebserv.systems\texpiresdate                 2027-02-08 15:13:22\n```\n\n## Contact us\nReaders are always welcomed to reach us on [Twitter](https://twitter.com/360Netlab) or email us to netlab at 360 dot cn.\n\n## IOC\n### C2\n```\nwebserv.systems\n194.165.16.24:53\n194.165.16.24:443\n```\n### Scanner\n```\n104.244.73.126\tLuxembourg|Luxembourg|Unknown\t53667|FranTech_Solutions\n109.201.133.100\tNetherlands|North_Holland|Amsterdam\t43350|NForce_Entertainment_B.V.\n162.247.74.27\tUnited_States|New_York|New_York_City\t4224|The_Calyx_Institute\n166.78.48.7\tUnited_States|Texas|Dallas\t33070|Rackspace_Hosting\n171.25.193.78\tSweden|Stockholm_County|Stockholm\t198093|Foreningen_for_digitala_fri-_och_rattigheter\n185.100.87.202\tRomania|Bucharest|Unknown\t200651|Flokinet_Ltd\n185.129.62.62\tDenmark|Region_Hovedstaden|Copenhagen\t57860|Zencurity_ApS\n185.220.100.240\tGermany|Bavaria|Nuremberg\t205100|F3_Netze_e.V.\n185.220.100.241\tGermany|Bavaria|Nuremberg\t205100|F3_Netze_e.V.\n185.220.100.242\tGermany|Bavaria|Nuremberg\t205100|F3_Netze_e.V.\n185.220.100.243\tGermany|Bavaria|Nuremberg\t205100|F3_Netze_e.V.\n185.220.100.246\tGermany|Bavaria|Nuremberg\t205100|F3_Netze_e.V.\n185.220.100.249\tGermany|Bavaria|Nuremberg\t205100|F3_Netze_e.V.\n185.220.100.250\tGermany|Bavaria|Nuremberg\t205100|F3_Netze_e.V.\n185.220.100.252\tGermany|Bavaria|Nuremberg\t205100|F3_Netze_e.V.\n185.220.100.254\tGermany|Bavaria|Nuremberg\t205100|F3_Netze_e.V.\n185.220.100.255\tGermany|Bavaria|Nuremberg\t205100|F3_Netze_e.V.\n185.220.101.134\tNetherlands|North_Holland|Amsterdam\t200052|Feral.io_Ltd\n185.220.101.136\tNetherlands|North_Holland|Amsterdam\t200052|Feral.io_Ltd\n185.220.101.140\tNetherlands|North_Holland|Amsterdam\t200052|Feral.io_Ltd\n185.220.101.143\tNetherlands|North_Holland|Amsterdam\t200052|Feral.io_Ltd\n185.220.101.144\tNetherlands|North_Holland|Amsterdam\t200052|Feral.io_Ltd\n185.220.101.151\tNetherlands|North_Holland|Amsterdam\t200052|Feral.io_Ltd\n185.220.101.155\tNetherlands|North_Holland|Amsterdam\t200052|Feral.io_Ltd\n185.220.101.161\tNetherlands|North_Holland|Amsterdam\t200052|Feral.io_Ltd\n185.220.101.162\tNetherlands|North_Holland|Amsterdam\t200052|Feral.io_Ltd\n185.220.101.164\tNetherlands|North_Holland|Amsterdam\t200052|Feral.io_Ltd\n185.220.101.166\tNetherlands|North_Holland|Amsterdam\t200052|Feral.io_Ltd\n185.220.101.168\tNetherlands|North_Holland|Amsterdam\t200052|Feral.io_Ltd\n185.220.101.172\tNetherlands|North_Holland|Amsterdam\t200052|Feral.io_Ltd\n185.220.101.174\tNetherlands|North_Holland|Amsterdam\t200052|Feral.io_Ltd\n185.220.101.176\tNetherlands|North_Holland|Amsterdam\t200052|Feral.io_Ltd\n185.220.101.181\tNetherlands|North_Holland|Amsterdam\t200052|Feral.io_Ltd\n185.220.101.191\tNetherlands|North_Holland|Amsterdam\t200052|Feral.io_Ltd\n185.220.101.34\tNetherlands|North_Holland|Amsterdam\t200052|Feral.io_Ltd\n185.220.101.37\tNetherlands|North_Holland|Amsterdam\t200052|Feral.io_Ltd\n185.220.101.39\tNetherlands|North_Holland|Amsterdam\t200052|Feral.io_Ltd\n185.220.101.40\tNetherlands|North_Holland|Amsterdam\t200052|Feral.io_Ltd\n185.220.101.42\tNetherlands|North_Holland|Amsterdam\t200052|Feral.io_Ltd\n185.220.101.43\tNetherlands|North_Holland|Amsterdam\t200052|Feral.io_Ltd\n185.220.101.46\tNetherlands|North_Holland|Amsterdam\t200052|Feral.io_Ltd\n185.220.101.5\tNetherlands|North_Holland|Amsterdam\t200052|Feral.io_Ltd\n185.220.101.50\tNetherlands|North_Holland|Amsterdam\t200052|Feral.io_Ltd\n185.220.101.51\tNetherlands|North_Holland|Amsterdam\t200052|Feral.io_Ltd\n185.220.101.53\tNetherlands|North_Holland|Amsterdam\t200052|Feral.io_Ltd\n185.220.101.54\tNetherlands|North_Holland|Amsterdam\t200052|Feral.io_Ltd\n185.220.101.56\tNetherlands|North_Holland|Amsterdam\t200052|Feral.io_Ltd\n185.220.101.57\tNetherlands|North_Holland|Amsterdam\t200052|Feral.io_Ltd\n185.220.101.61\tNetherlands|North_Holland|Amsterdam\t200052|Feral.io_Ltd\n185.56.80.65\tNetherlands|South_Holland|Capelle_aan_den_IJssel\t43350|NForce_Entertainment_B.V.\n193.218.118.158\tUkraine|Kiev|Unknown\tNone;\n194.32.107.159\tRomania|Romania|Unknown\tNone;\n194.32.107.187\tRomania|Romania|Unknown\tNone;\n194.88.143.66\tItaly|Lombardy|Metropolitan_City_of_Milan\t49367|Seflow_S.N.C._Di_Marco_Brame'_&_C.\n199.195.250.77\tUnited_States|New_York|New_York_City\t53667|FranTech_Solutions\n23.129.64.216\tUnited_States|Washington|Seattle\t396507|Emerald_Onion\n23.154.177.4\tNorth_America_Regions|North_America_Regions|Unknown\tNone;\n45.13.104.179\tFrance|Ile-de-France|Paris\t57199|MilkyWan\n45.154.255.147\tSweden|Stockholm_County|Stockholm\t41281|KeFF_Networks_Ltd\n45.61.185.90\tUnited_States|United_States|Unknown\t8100|QuadraNet_Enterprises_LLC\n46.166.139.111\tNetherlands|South_Holland|Capelle_aan_den_IJssel\t43350|NForce_Entertainment_B.V.\n5.2.69.50\tNetherlands|Flevoland|Dronten\t60404|Liteserver_Holding_B.V.\n51.15.43.205\tNetherlands|North_Holland|Haarlem\t12876|Online_S.a.s.\n62.102.148.68\tSweden|Stockholm_County|Akersberga\t51815|IP-Only_Networks_AB\n62.102.148.69\tSweden|Stockholm_County|Akersberga\t51815|IP-Only_Networks_AB\n81.17.18.62\tSwitzerland|Canton_of_Ticino|Unknown\t51852|Private_Layer_INC\n```\n### Downloader\n```\nhxxp://179.60.150.23:8000/xExportObject.class\nldap://179.60.150.23:1389/o=tomcat\nhxxp://194.165.16.24:8229/b1t_1t.sh\nhxxp://194.165.16.24:8228/b1t\nhxxp://194.165.16.24:8228/b1t\nhxxp://194.165.16.24:8228/_run.sh\nhxxp://194.165.16.24:8228/run.sh\nhxxp://194.165.16.24:8228/share.sh\nhxxp://194.165.16.24:8228/b1t\nhxxp://194.165.16.24:8228/run.sh\nhxxp://194.165.16.24:8228/run.sh\nhxxp://194.165.16.24:8229/b4d4b1t.elf\n```\n### Sample MD5\n```\n027d74534a32ba27f225fff6ee7a755f\n0a0c43726fd256ad827f4108bdf5e772\n24c49e4c75c6662365e10bbaeaeecb04\n2e5724e968f91faaf156c48ec879bb40\n3192e913ed0138b2de32c5e95146a24a\n40024288c0d230c0b8ad86075bd7c678\n43fcb5f22a53a88e726ebef46095cd6b\n59690bd935184f2ce4b7de0a60e23f57\n5f77c32c37ae7d25e927d91eb3b61c87\n6b42a9f10db8b11a15006abced212fa4\n6c05637c29b347c28d05b937e670c81e\n7ef9d37e18b48de4b26e5d188a383ec8\n7f4e74e15fafaf3f8b79254558019d7f\n989dd7aa17244da78309d441d265613a\ndd4b6e2750f86f2630e3aea418d294c0\ne82135951c3d485b7133b9673194a79e\nfd84b2f06f90940cb920e20ad4a30a63\n\n```"}]],"markups":[],"sections":[[10,0],[1,"p",[]]],"ghostVersion":"3.0"}