New Threat: B1txor20, A Linux Backdoor Using DNS Tunnel
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 encoding
to 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.
- SHELL
- Proxy
- Execute arbitrary commands
- Install Rootkit
- 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 valueab3b49d10ec42c38b1093b8ce9ad12af
of 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 theTaskInfo
section 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