# Mirai_ptea Botnet is Exploiting Undisclosed KGUARD DVR Vulnerability **[blog.netlab.360.com/mirai_ptea-botnet-is-exploiting-undisclosed-kguard-dvr-vulnerability-en/](https://blog.netlab.360.com/mirai_ptea-botnet-is-exploiting-undisclosed-kguard-dvr-vulnerability-en/)** Hui Wang July 1, 2021 1 July 2021 / [nday](https://blog.netlab.360.com/tag/nday/) ## 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,](https://www.kguard.com.tw/) 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 ----- **DeviceType** **ProductType** **HardVersion** **DefDeviceName** 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 ----- **DeviceType** **ProductType** **HardVersion** **DefDeviceName** 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 ----- **DeviceType** **ProductType** **HardVersion** **DefDeviceName** 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 pseudoprocess 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. ``` rkz2f5u57cvs3kdt6amdku2uhly2esj7m2336dttvcygloivcgsmxjjnuickasbuatxajrovi4lvd2zjuejivz ``` ----- 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](https://twitter.com/360Netlab) `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("I",tmp[i:i+4])[0]) port.append(struct.unpack("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("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" ``` -----