Mirai_ptea Botnet is Exploiting Undisclosed KGUARD DVR Vulnerability

Overview


On 2021-06-22 we detected a sample of a mirai variant that we named mirai_ptea propagating through a new vulnerability targeting KGUARD DVR. Coincidently, a day later, on June 23, we received an inquiry from the security community asking if we had seen a new DDoS botnet, cross-referencing some data, it was exactly this botnet that we had just discovered.



Timeline


 * 2021-03-22 Our historical data indicates the first probe against this vulnerability
 * 2021-06-22 We observed the mirai_ptea sample exploiting this vulnerability to spread
 * 2021-06-23 We got a tip from the security community that this botnet was being used for ongoing DDoS attacks.
 * 2021-06-25 mirai_aurora, another mirai variant, starts to use this vulnerability to propagate



Vulnerability analysis


Given that we have not found public information on this vulnerability, we will hide some of the key information here to prevent the vulnerability from being further abused.


One program on the KGUARD DVR firmware listens on port ***** at 0.0.0.0 to remotely execute system commands without authentication. The firmware released after 2017 seems to have this fixed by modifying the listening address to 127.0.0.1. Some of the exploited payloads are as follows.





Analysis of affected devices


We have discovered at least 3,000 or so online devices still have the vulnerability. The affected devices are as follows:





DeviceType
ProductType
HardVersion
DefDeviceName




D1004NR
DVR4-1600
DM-268A
DVR4-1600


D1004NR
HY-DVR
DM-268
720P-HY04N


D1004NR
HY-DVR
DM-268A
720P-HY04N


D1004NR
HY-DVR
DM-274
720P-HY04N


D1004NR
HY-DVR
DM-274B
720P-HY04N


D1004NR
NHDR
DM-274
NHDR-3204AHD


D1004NR
RL-AHD4n
DM-268
720P-HY04N


D1008NR
1093/508N-DVRBM08H
DM-292
720P-HY08N


D1008NR
DVR8-1600
DM-298
DVR8-1600


D1008NR
DVR8-HDA10L
DM-292
DVR8-HDA10L


D1008NR
HD881
DM-292
HD881


D1008NR
HY-DVR
DM-292
720P-HY08N


D1008NR
HY-DVR
DM-298
720P-HY08N


D1008NR
NHDR
DM-298
NHDR-3208AHD


D1008NR
RL-AHD8n
DM-292
720P-HY08N


D1016NR
DVR16-HDA10L
DM-303
DVR16-HDA10L


D1016NR
HD1681
DM-303
HD1681


D1016NR
HY-DVR
DM-303A
720P-HY16N


D1016NR
HY-DVR
DM-310
720P-HY16N


D1016NR
HY-DVR
DM-310A
720P-HY16N


D1016NR
NHDR
DM-310
NHDR-3216AHD


D1016NR
RL-MHD16n(21A)
DM-310A
720P-HY16N


D1104
HY-DVR
DM-290A
1080P-HY04


D1104
NHDR
DM-307
NHDR-5304AHD


D1104NR
HD1T4
DM-291A
1080P-04


D1104NR
HD481
DM-291
HD481


D1104NR
HRD-E430L
DM-291A
HRD-E430L


D1104NR
HY-DVR
DM-284
1080P-HY04N


D1104NR
HY-DVR
DM-291
"Panda


D1104NR
HY-DVR
DM-291
1080P-HY04N


D1104NR
HY-DVR
DM-291A
1080P-HY04N


D1104NR
HY-DVR
DM-291C
LRA3040N


D1104NR
NHDR
DM-307
NHDR-5104AHD


D1104NR
SDR-B73303
DM-291A
SDR-B73303


D1104NR
SVR9204H
DM-291A
1080P-HY04N


D1108NR
1093/538P
DM-290
1080P-HY08N


D1108NR
DVR8-4575
DM-290
DVR8-4575


D1108NR
DVR8-HDA10P
DM-290
DVR8-HDA10P


D1108NR
HRD-E830L
DM-290A
HRD-E830L


D1108NR
HY-DVR
DM-290
1080P-HY08N


D1108NR
HY-DVR
DM-290A
1080P-HY08N


D1108NR
HY-DVR
DM-290A
LRA3080N


D1108NR
NHDR
DM-307
NHDR-5108AHD


D1108NR
RL-AHD8p
DM-290
1080P-HY08N


D1108NR
SDR-B74301
DM-290A
SDR-B74301


D1108NR
SDR-B74303
DM-290A
SDR-B74303


D1116
HY-DVR
DM-300
EHR-5164


D1116NR
HRD-E1630L
DM-295
HRD-E1630L


D1116NR
HY-DVR
DM-295
1080P-HY16N


D1116NR
HY-DVR
DM-295
LRA3160N


D1116NR
HY-DVR
DM-299
1080P-HY16N


D1116NR
SDR-B75303
DM-295
SDR-B75303


D1132NR
HY-DVR
DM-300
1080P-HY32


D2116NR
SDR-B85300
DM-300
SDR-B85300


D973215U
F9-DVR32
DM-195
F9-DVR32


D9804AHD
DVR
DM-210
391115


D9804NAHD
AHD7-DVR4
DM-239
AHD7-DVR4


D9804NAHD
DVR
DM-239
720P-DVR04ND


D9804NAHD
NHDR
DM-239
NHDR-3104AHD-II


D9808NRAHD
AHD7-DVR8
DM-228
AHD7-DVR8


D9808NRAHD
DVR
DM-228



D9808NRAHD
DVR
DM-228
391116


D9808NRAHD
NHDR
DM-228
NHDR-3108AHD-II


D9808NRAHD
NHDR
DM-228
NHDR3108AHDII


D9816NAHD
DVR
DM-233
720P-DVR016N


D9816NAHD
NHDR
DM-233
NHDR3116AHDII


D9816NRAHD
AHD7-DVR16
DM-229
AHD7-DVR16


D9816NRAHD
DVR
DM-229
720P-DVR016NB


D9904
D9904
DM-237
1080P-DVR04


D9904
DVR
DM-237
1080P-DVR04


D9904
NHDR
DM-237
NHDR-5204AHD


D9904NR
DVR
DM-244
1080P-DVR04N


D9904NR
DVR
DM-244
BCS-VAVR0401M


D9904NR
HY-DVR
DM-244
CVD-AF04S


D9904NR
N420
DM-244
1080P-DVR04N


D9904NR
NHDR
DM-244
NHDR-5004AHD-II


D9904NR
NHDR
DM-244
NHDR5004AHDII


D9908
DVR
DM-245
BCS-VAVR0802Q


D9908
NHDR
DM-245
NHDR-5208AHD


D9908AHD
DVR
DM-246
1080P-DVR08A


D9908NR
AHD10-DVR8
DM-237
AHD10-DVR8


D9908NR
DVR
DM-237
1080P-DVR08N


D9908NR
DVR
DM-237
SVR9008ATHD/C


D9908NR
HY-DVR
DM-237
CVD-AF08S


D9908NR
N820
DM-237
1080P-DVR08N


D9908NR
NHDR
DM-237
NHDR-5008AHD-II


D9916NR
DVR
DM-245
1080P-DVR016NAT;UI


D9916NR
DVR
DM-245
HR-31-211620;UI


D9916NR
HY-DVR
DM-245
CVD-AF16S


D9916NR
NHDR
DM-245
NHDR-5016AHD-II


D9916NRAHD
DVR
DM-246
1080P-DVR016NA


D9916NRAHD
N1620
DM-246
1080P-DVR016NA


H1104W
SNR-73200W
DM-339
SNR-73200W


H1106W
LHB806
DM-291B
LHB806


H1106W
LHB906
DM-291B
LHB906






Bot scale analysis


We are able to see a portion of the infected bots, the following is a daily active trend：





The geographic distribution of Bot source IPs is as follows, mainly concentrated in the United States, Korea and Brazi：





Sample Analysis


Let’s take a look a the the following samples


Verdict:mirai_ptea
MD5:c6ef442bc804fc5290d3617056492d4b
ELF 32-bit LSB executable, ARM, version 1, statically linked, stripped 
Packer:No
Lib:uclibc



c6ef442bc804fc5290d3617056492d4b is a variant of Mirai, which we call Mirai_ptea based on its use of Tor Proxy to communicate with C2 and the TEA algorithm (Tiny Encryption Algorithm) to hide sensitive resource information. When ptea runs, it prints out in the Console: come at me krebs rimasuta go BRRT.


This sample is very similar to Mirai at the host behavior level, so we will not cover it here; At the network traffic level, Tor proxy is used, with a large number of proxy nodes embedded in the sample, and Tor-C2 is encrypted. In the following section we will focus on the encryption method and communication protocol.



Encryption algorithm


Mirai_ptea encrypts all sensitive resource information and stores it in a certain order. The string information seen when the sample is opened in IDA is shown below, with almost no readable information.





The following code snippet is from the decryption-related functions in the sample, which can be determined to use the TEA algorithm by the constants 0xC6EF3720 & 0X61C88647.



The key is：


0xC26F6A52 0x24AA0006 0x8E1BF2C5 0x4BA51F8C



We wrote a decryption script(see appendix), through which we can obtain all the decrypted sensitive resources and their table entry information, part of the resource information is shown below.



Mirai_ptea has two ways of operation when using encrypted resources


 * The traditional Mirai way: Decrypt an encrypted item, take the value, re-encrypt the decrypted item, i.e. var_unlock-->var_get-->var_lock. For example, the console information is taken by this method.
   
   


The value of table entry 0x11 is exactly: come at me krebs rimasuta go BRRT.


 * Mirai_ptea’s way: Decrypt multiple encrypted items, taking the value, and re-encrypt the decrypted items, i.e. rangeVar_unlock-->var_get-->rangeVar_lock. For example, this method is used when getting the disguised process name.
   
   


The values of the table entries 0x2c to 0x2c+10 shown below are the exact 11 pseudo-process names that can be chosen.


index 0x2c, value = /bin/sh
index 0x2d, value = telnetd
index 0x2e, value = upnpc-static
index 0x2f, value = wsdd
index 0x30, value = proftpd
index 0x31, value = mini_httpd
index 0x32, value = udevd
index 0x33, value = /sbin/udhcpc
index 0x34, value = boa
index 0x35, value = /usr/sbin/inetd
index 0x36, value = dnsmasq




Communication Protocol


An overview of the network traffic in Mirai_ptea is provided below.



The whole process can be divided into 3 steps as follows.


1: Establishing a connection with the proxy node


2: Establishing a connection with Tor C2


3: Communicate with C2 via ptea's custom protocol to receive attack commands from C2.



0x1.Establishing a connection with the proxy


The Mirai_ptea sample has two sets of proxies built into it, with table entries 0x2a and 0x2b in the encrypted resource. When the Bot sample runs, one of the two sets of proxies is selected at random, and then one proxy node of the selected sets is connected by the following code snippet.



There are 38 proxy nodes in 0x2a in the format of ip:port



And there are 334 proxy nodes in 0x2b, in the format of ip, and the port of this group of proxies is fixed at 9050.



See the appendix for a detailed list of proxies.



0x2. Connecting to C2 via the Tor-Proxy protocol





You can see that C2 has the table entry 0xD in the encrypted resource, and after decrypting it, get the following string.


rkz2f5u57cvs3kdt6amdku2uhly2esj7m2336dttvcygloivcgsmxjjnuickasbuatxajrovi4lvd2zjuejivzrb3vobuoezbc6z3gtu6b3r5tce.onion



Excluding the .onion at the end of the above string and splitting it by length 16, then splicing it with the .onion string at the end, we get the following 7 C2s.


rkz2f5u57cvs3kdt.onion
6amdku2uhly2esj7.onion
m2336dttvcygloiv.onion
cgsmxjjnuickasbu.onion
atxajrovi4lvd2zj.onion
uejivzrb3vobuoez.onion
bc6z3gtu6b3r5tce.onion




0x3. Communicate with the C2s via custom protocols for registration, heartbeat, and attack as follows


 * Registration
   
   


msg parsing
----------------------------------------------------------------
3e c7 e3 1e 37 47 61 20						----->hardcoded msg from Bot
b1 2f de ce cb 89 e1 a0						----->cmd from C2,ask Bot to upload info
3a 31 34 b5 02 00							----->hardcoded 6 bytes msg from Bot
b4 a3 e1 16									----->ip of infected device
04											----->group string length
74 65 73 74								    ----->group string
79			                                ----->padding



 * Heartbeat
   
   


msg parsing
----------------------------------------------------------------
2a 23						-----> random 2 bytes msg from Bot
2a 23						-----> random 2 bytes msg from C2



 * Attack command The first 4 bytes of the attack command, AD AF FE 7F are fixed phantom numbers, and the rest of the attack command is similar to mirai's attack command format


00000000: AD AF FE 7F 1E 00 00 00  00 01 B9 98 42 65 20 00  ............Be .
00000010: 42 65 20 00     




DDoS attack activity


This botnet has been busy launching DDoS attacks, the following figure shows some DDoS attack instructions of the botnet that we observed.





Contact us


Readers are always welcomed to reach us on twitter , or email to netlabat[at]360.cn.



IoC



Tor-C2


bc6z3gtu6b3r5tce.onion:3742
cgsmxjjnuickasbu.onion:992
uejivzrb3vobuoez.onion:5353
rkz2f5u57cvs3kdt.onion:280
atxajrovi4lvd2zj.onion:110
6amdku2uhly2esj7.onion:513
m2336dttvcygloiv.onion:666




Sample MD5


c6ef442bc804fc5290d3617056492d4b
f849fdd79d433e2828473f258ffddaab




Downloader URL


http://193[.177.182.221/boot




Scanner IP


205.185.117.21	AS53667|FranTech_Solutions	United_States|Nevada|Las_Vegas
205.185.114.55	AS53667|FranTech_Solutions	United_States|Nevada|Las_Vegas
68.183.109.6	AS14061|DigitalOcean,_LLC	United_States|New_York|New_York_City
67.205.163.141	AS14061|DigitalOcean,_LLC	United_States|New_York|New_York_City
165.227.88.215	AS14061|DigitalOcean,_LLC	United_States|New_York|New_York_City




Proxys


---------proxys at index 0x2a，count=38---------
149.202.9.7:9898
91.134.216.103:16358
84.32.188.34:1157
51.178.185.237:32
65.21.16.80:23560
149.202.9.14:19765
146.59.11.109:5089
195.189.96.61:29582
84.32.188.37:1454
51.195.209.80:26848
5.199.174.242:27931
95.179.158.147:22413
146.59.11.103:1701
185.150.117.10:29086
149.56.154.210:24709
135.148.11.151:3563
51.195.152.255:25107
45.79.193.124:7158
135.148.11.150:5560
185.150.117.41:20790
135.125.250.120:14498
172.106.70.135:692
195.189.96.60:9700
172.106.70.134:25054
149.56.154.211:21299
108.61.218.205:29240
51.178.185.236:21685
51.81.139.251:6255
51.255.237.164:963
51.81.139.249:32380
139.162.45.218:5165
65.21.16.94:28056
207.148.74.163:32389
172.104.100.78:1039
45.32.8.100:19759
141.164.46.133:2205
172.105.36.167:10843
172.105.180.239:19531

---------proxys at index 0x2b，count=334，port=9050---------
Too many, not list here, you can get them via the IDA script




Appendix（IDA Decrypt script）


# IDAPYTHON SCRIPT for md5 c6ef442bc804fc5290d3617056492d4b only.
# Tested at ida 7.0
from ctypes import *
import struct
print "-------------------decryption start------------------------"

key=[0xC26F6A52,0x24AA0006,0x8E1BF2C5,0x4BA51F8C]
def tea_dec(buf,key):
    rbuf=""
    fmt = '>' + str(len(buf)/4) + 'I'
    tbuf= struct.unpack_from(fmt,buf)
    j=0
    for i in range(0,len(tbuf)/2):
        
        v1=c_uint32(tbuf[i+j])
        v2=c_uint32(tbuf[i+1+j])

        sum=c_uint32(0xC6EF3720)
        while(sum.value):
            v2.value -= ((v1.value>>5)+key[3])    ^(v1.value+sum.value)^  ((v1.value<<4)+key[2])
            v1.value -= ((v2.value>>5)+key[1])   ^(v2.value+sum.value)^ ((v2.value<<4)+key[0])
            sum.value+=0x61C88647
        rbuf +=struct.pack(">I",v1.value)+struct.pack(">I",v2.value)
        j+=1
    return rbuf
def getbuff(addr):
    buf = ""
    while idc.get_bytes(addr, 2) != "\x00\x00":
        buf += idc.get_bytes(addr, 1)
        addr += 1

    return buf



# pay attention to function at 0x0000D074
a=getbuff(idc.get_wide_dword(0x00019C9C))

    

buf=[]
#0x19c9c-0x199f0 --> 684
for i in range(0,684,12):
    offset=idc.get_wide_word(0x000199F4+i)
    length=idc.get_wide_word(0x000199F4+i+2)

    buf.append(a[offset:offset+length])
    
c2=[]
#684/12 --> 57
for i in range(57):
    decbuf=tea_dec(buf[i],key)

    if(".onion" in decbuf):
        c2.append(decbuf)
    print "index %x, value = %s" %(i,decbuf)    
print "-------------------decryption end---------------"

proxya=tea_dec(buf[0x2a],key)
pacnt=struct.unpack("<H",proxya[2:4])


proxy=[]
port=[]
tmp=proxya[4:4+6*(pacnt[0])]
print "------------proxys at index 0x2A, count= %d------------" %(pacnt[0])
for i in range(0,len(tmp),6):
    proxy.append(struct.unpack(">I",tmp[i:i+4])[0])
    port.append(struct.unpack("<H",tmp[i+4:i+6])[0])
for i in range(pacnt[0]):
    a=struct.pack(">I",proxy[i])
    ip=""
    for j in range(4):
        ip+=str(ord(a[j]))
        if j!=3:
            ip+="."
    
    print"%s:%d" %(ip,port[i])



proxyb=tea_dec(buf[0x2b],key)
pbcnt=struct.unpack("<H",proxyb[2:4])
fmt = '>' + str(pbcnt[0]) + 'I'
tmp=proxyb[4:4*(pbcnt[0]+1)]
print "------------proxys at index 0x2B, count= %d------------" %(pbcnt[0])
xxxxx=struct.unpack(fmt,tmp)
for i in xxxxx:
    a=struct.pack(">I",i)
    ip=""
    for i in range(4):
        ip+=str(ord(a[i]))
        if i!=3:
            ip+="."
    print ip


print "-------------------------onion info--------------"    
if len(c2)!=0:
    for i in c2:
        
        pos=i.find(".onion")

        for j in range(0,pos,16):
            print i[j:16+j]+".onion"
else:
    print "Don't find the onion c2"