Detecting and preventing malicious activity such as botnet attacks is a critical area of focus for threat intel analysts, security operators, and threat hunters. Taking up the Mozi botnet as a case study, this blog post demonstrates how to use open source tools, analytical processes, and the Elastic Stack to perform analysis and enrichment of collected data irrespective of the campaign. This will allow you to take the lessons and processes outlined below to your organization and apply them to your specific use cases. The Mozi botnet has been leveraging vulnerable Internet of Things (IoT) devices to launch campaigns that can take advantage of the force multiplication provided by a botnet (Distributed Denial of Service (DDoS), email spam, brute-force, password spraying, etc.). Mozi was first reported by the research team at 360Netlab in December 2019 and has continued to make up a large portion of IoT network activity across the Internet-at-large. As reported by 360Netlab, the botnet spreads via the use of weak and default remote access passwords for targeted devices as well as through multiple public exploits. The Mozi botnet communicates using a Distributed Hash Table (DHT) which records the contact information for other nodes in the botnet. This is the same serverless mechanism used by file sharing peer-to-peer (P2P) clients. Once the malware has accessed a vulnerable device, it executes the payload and subsequently joins the Mozi P2P network. The newly infected device listens for commands from controller nodes and also attempts to infect other vulnerable devices. Mozi targets multiple IoT devices and systems, mainly focused on Small Office Home Office (SOHO) networking devices, Internet-connected audio visual systems, and theoretically any 32-bit ARM device. CollectionWhen performing data analysis, the more data that you have, the better. Analysis of malware campaigns are no different. With a paid subscription to VirusTotal, you can collect huge amounts of data for analysis, but we wanted an approach for independent researchers or smaller organizations that may not have this premium service. To do that, we decided to keep to our roots at Elastic and leverage open source datasets to avoid a paywall that could prevent others from using our processes. To begin, we started with a handful of Mozi samples collected from ThreatFox. ThreatFox is an open source platform from Abuse.ch with the goal of sharing malware indicators with the security research community. Using cURL, we queried the ThreatFox API for the Mozi tag. This returned back JSON documents with information about the malware sample, based on the tagged information. curl -X POST https://threatfox-api.abuse.ch/api/v1/ -d '{ "query": "taginfo", "tag": "Mozi", "limit": 1 }' Code block 1 - cURL request to ThreatFox API -X POST - change the cURL HTTP method from GET (default) to POST as we’re going to be sending data to the ThreatFox API https://threatfox-api.abuse.ch/api/v1/ - this is the ThreatFox API endpoint -d - this is denoting that we’re going to be sending data query: taginfo - the type of query that we’re making, taginfo in our example tag: Mozi - the tag that we’ll be searching for, “Mozi” in our example limit: 1 - the number of results to return, 1 result in our example, but you can return up to 1000 results This returned the following information: { "query_status": "ok", "data": [ { "id": "115772", "ioc": "nnn.nnn.nnn.nnn:53822", "threat_type": "botnet_cc", "threat_type_desc": "Indicator that identifies a botnet command&control server (C&C)", "ioc_type": "ip:port", "ioc_type_desc": "ip:port combination that is used for botnet Command&control (C&C)", "malware": "elf.mozi", "malware_printable": "Mozi", "malware_alias": null, "malware_malpedia": "https:\/\/malpedia.caad.fkie.fraunhofer.de\/details\/elf.mozi", "confidence_level": 75, "first_seen": "2021-06-15 08:22:52 UTC", "last_seen": null, "reference": "https:\/\/bazaar.abuse.ch\/sample\/832fb4090879c1bebe75bea939a9c5724dbf87898febd425f94f7e03ee687d3b\/", "reporter": "abuse_ch", "tags": [ "Mozi" ] } ] Code block 2 - Response from ThreatFox APINow that we have the file hashes of several samples, we can download the samples using the Malware Bazaar API. Malware Bazaar is another open source platform provided by Abuse.ch. While ThreatFox is used to share contextual information about indicators, Malware Bazaar allows for the actual collection of malware samples (among other capabilities). Just like with ThreatFox, we’ll use cURL to interact with the Malware Bazaar API, but this time to download the actual malware samples. Of note, the Malware Bazaar API can be used to search for samples using a tag (“Mozi”, in our example), similar to how we used the ThreatFox API. The difference is that the ThreatFox API returns network indicators that we’ll use later on for data enrichment. curl -X POST https://mb-api.abuse.ch/api/v1 -d 'query=get_file&sha256_hash=832fb4090879c1bebe75bea939a9c5724dbf87898febd425f94f7e03ee687d3b' -o 832fb4090879c1bebe75bea939a9c5724dbf87898febd425f94f7e03ee687d3b.raw Code block 3 - cURL request to Malware Bazaar API
-X POST - change the cURL HTTP method from GET (default) to POST as we’re going to be sending data to the Malware Bazaar API
https://mb-api.abuse.ch/api/v1 - this is the Malware Bazaar API endpoint
-d - this is denoting that we’re going to be sending data
query: get_file - the type of query that we’re making, get_file in our example
sha256_hash - the SHA256 hash we’re going to be collecting, “832fb4090879c1bebe75bea939a9c5724dbf87898febd425f94f7e03ee687d3b” in our example
-o - the file name we’re going to save the binary as
This will save a file locally named 832fb4090879c1bebe75bea939a9c5724dbf87898febd425f94f7e03ee687d3b.raw. We want to make a raw file that we’ll not modify so that we always have an original sample for archival purposes. This downloads the file as a Zip archive. The passphrase to extract the archive is infected. This will create a local file named 832fb4090879c1bebe75bea939a9c5724dbf87898febd425f94f7e03ee687d3b.elf. Going forward, we’ll use a shorter name for this file, truncated-87d3b.elf, for readability.
UnpackingNow that we have a few samples to work with we can look at ripping out strings for further analysis. Once in our analysis VM we took a stab at running Sysinternals Strings over our sample:
$ strings truncated-87d3b.elf
ELF
*UPX!
ELF
$Bw
(GT
...
Code block 3 - Strings output from the packed Mozi sampleRight away we see that we have a UPX packed ELF binary from the “ELF” and “UPX!” text. UPX is a compression tool for executable files, commonly known as “packing”. So the next logical step is to decompress the ELF file with the UPX program. To do that, we’ll run upx with the -d switch.
$ upx -d truncated-87d3b.elf
Ultimate Packer for eXecutables
Copyright (C) 1996 - 2020
UPX 3.96w Markus Oberhumer, Laszlo Molnar & John Reiser Jan 23rd 2020
File size Ratio Format Name
upx.exe : upx: truncated-87d3b.elf : CantUnpackException: p_info corrupted
Code block 4 - UPX output from corrupted Mozi sampleAnother road-block: the p_info section of the file appears to be corrupted. p_info is the sum of two sections from a file, p_blocksize and p_filesize. After a quick search for the error message, we landed on a CUJOAI Anti-Unpacking blog explaining the header corruptions commonly used in IoT malware to disrupt automated analysis tools.
Using this information, we cracked open our binary in xxd, a HEX dumper, to see which corruption we were dealing with. As described in the CUJOAI blog, the p_info blocks represent the sum of the p_filesize blocks and the p_blocksize blocks. This section begins with the 8 bytes after the UPX! text, and has been overwritten with zeros (the 8 bytes starting at 0x84).
$ xxd truncated-87d3b.elf
00000000: 7f45 4c46 0101 0161 0000 0000 0000 0000 .ELF...a........
00000010: 0200 2800 0100 0000 1057 0200 3400 0000 ..(......W..4...
00000020: 0000 0000 0202 0000 3400 2000 0200 2800 ........4. ...(.
00000030: 0000 0000 0100 0000 0000 0000 0080 0000 ................
00000040: 0080 0000 0de0 0100 0de0 0100 0500 0000 ................
00000050: 0080 0000 0100 0000 b07a 0000 b0fa 0600 .........z......
00000060: b0fa 0600 0000 0000 0000 0000 0600 0000 ................
00000070: 0080 0000 10f1 8f52 5550 5821 1c09 0d17 .......RUPX!....
00000080: 0000 0000 0000 0000 0000 0000 9400 0000 ................
00000090: 5e00 0000 0300 0000 f97f 454c 4601 7261 ^.........ELF.ra
000000a0: 000f 0200 28dd 0001 0790 b681 0334 ee07 ....(........4..
000000b0: ec28 04db 1302 0bfb 2000 031b be0a 0009 .(...... .......
...
Code block 5 - HEX view of the corrupted Mozi sampleThe CUJOAI blog states that if you manually update the values of the p_filesize blocks and the p_blocksize blocks with the value of the p_info, this will fix the corruption issue. Below we can see the p_info section in HEX, and we can use that to manually update the p_filesize and p_blocksize sections, which will allow us to unpack the binary (the 4 bytes starting at 0x1e110).
$ xxd truncated-87d3b.elf
...
0001e0c0: 1914 a614 c998 885d 39ec 4727 1eac 2805 .......]9.G'..(.
0001e0d0: e603 19f6 04d2 0127 52c9 9b60 00be 273e .......'R....'> 0001e0e0: c00f 5831 6000 0000 0000 90ff 0000 0000 ..X1 ...........
0001e0f0: 5550 5821 0000 0000 5550 5821 0d17 0308 UPX!....UPX!....
0001e100: 5199 6237 591c 321c d001 0000 b800 0000 Q.b7Y.2.........
0001e110: 7c2a 0400 5000 0011 8000 0000 |
*..P....... Code block 6 - p_info HEX data from the corrupted Mozi sampleFirst, let’s open the file with Vim. As we can see, it is just a UPX file as denoted by the UPX!. $ vim truncated-87d3b.elf ^?ELF^A^A^Aa^@^@^@^@^@^@^@^@^B^@(^@^A^@^@^@^PW^B^@4^@^@^@^@^@^@^@^B^B^@^@4^@ ^@^B^@(^@^@^@^@^@^A^@^@^@^@^@^@^@^@^@^@^@^@^@^Mà^A^@^Mà^A^@^E^@^@^@^@^@^@^A^@^@^@°z^@^@°ú^F^@°ú^F^@^@^@^@^@^@^@^@^@^F^@^@^@^@^@^@^PñRUPX!^\ Code block 7 - Corrupted Mozi sample in VimUsing the xxd plugin for Vim, we can convert this to HEX so that we can make our modifications. This is achieved by typing :%!xxd, which will show us the HEX output for the file. 00000000: 7f45 4c46 0101 0161 0000 0000 0000 0000 .ELF...a........ 00000010: 0200 2800 0100 0000 1057 0200 3400 0000 ..(......W..4... 00000020: 0000 0000 0202 0000 3400 2000 0200 2800 ........4. ...(. 00000030: 0000 0000 0100 0000 0000 0000 0080 0000 ................ 00000040: 0080 0000 0de0 0100 0de0 0100 0500 0000 ................ 00000050: 0080 0000 0100 0000 b07a 0000 b0fa 0600 .........z...... 00000060: b0fa 0600 0000 0000 0000 0000 0600 0000 ................ 00000070: 0080 0000 10f1 8f52 5550 5821 1c09 0d17 .......RUPX!.... 00000080: 0000 0000 0000 0000 0000 0000 9400 0000 ................ 00000090: 5e00 0000 0300 0000 f97f 454c 4601 7261 ^.........ELF.ra 000000a0: 000f 0200 28dd 0001 0790 b681 0334 ee07 ....(........4.. 000000b0: ec28 04db 1302 0bfb 2000 031b be0a 0009 .(...... ....... Code block 8 - Corrupted Mozi sample in Vim with XXD pluginNext, we can just update bytes 0x84 - 0x8b (that we identified as having the zero’d out p_filesize and p_blocksize) with the HEX value for p_info (7c2a 0400). 00000080: 0000 0000 7c2a 0400 7c2a 0400 9400 0000 .... | *.. | *...... Code block 9 - Updated p_filesize and p_blocksize HEX valuesLet’s reset the file back using :%!xxd -r, save the file and exit Vim (:wq). Finally, let’s try to unpack the file now that we’ve manually adjusted the HEX values. $ upx -d truncated-87d3b.elf Ultimate Packer for eXecutables Copyright (C) 1996 - 2020 UPX 3.96 Markus Oberhumer, Laszlo Molnar & John Reiser Jan 23rd 2020 File size Ratio Format Name |
---|
273020 Ingest Node Pipelines, then click Create pipeline.
Figure 1 - Creating Ingest Node Pipeline for ThreatFox dataNext, we’ll give our pipeline a name, optionally a version, and a description. From this view you can manually add processors and configure them to your liking. To give you a head start, we've provided the ThreatFox pipeline definition here you can paste in. Click Import processors and paste the contents of this pipeline definition: pipeline.json. When you click Load and overwrite, you'll have each processor listed there as we've configured it. From here you can tweak it to your needs, or just scroll down and click Create pipeline.
https://www.elastic.co/blog/collecting-and-operationalizing-threat-data-from-the-mozi-botnet
Login to add comment
Other posts in this group
Version 7.17.27 of the Elastic Stack was released today. We recommend you upgrade to this latest version. We recommend 7.17.27 over the previous versi