Android/MMRAT : Additional Analysis

Hello!

Today, I wanted to talk about the Android MMRAT Banking Trojan. This trojan has a ton of features and was covered very well by a recent Trend Micro blog post here:

and for those of you wanting IOCs, they posted those here:

https://www.trendmicro.com/content/dam/trendmicro/global/en/research/23/h/mmrat-carries-out-bank-fraud-via-fake-app-stores/IOC_stealthy-android-malware-mmrat-carries-out-bank-fraud-via-fake-app-stores.txt

I used this information, a long with some PCAPs I scored to make a few rules in the ETOPEN ruleset:

  • 2048084 ET MOBILE_MALWARE Android/MMRAT Data Exfiltration Attempt
  • 2048085 ET MOBILE_MALWARE Android/MMRAT CnC Checkin M1
  • 2048086 ET MOBILE_MALWARE Android/MMRAT CnC Checkin M2

I want to make sure its known before I dive into the rest of this post, that I’m not necessarily a reverse engineer by trade. I picked up a thing or two over time, and I just happen to notice patterns in the network traffic as I’m analyzing it. If you happen to be a professional reverse engineer and you would like to add your two cents, please feel free to do so, as we can all learn from your experience.

I wanted to talk about the network traffic I observed to create these rules. First, I’m going to talk about rule 2048084, since its a straightforward HTTP protocol rule:

alert http $HOME_NET any -> $EXTERNAL_NET any (msg:"ET MOBILE_MALWARE Android/MMRAT Data Exfiltration Attempt"; flow:established,to_server; http.method; content:"POST"; http.uri; content:"/system/apps"; http.header; content:"Authorization|3a 20|Bearer"; http.user_agent; content:"okhttp/"; http.request_body; content:"|7b 22|deviceId|22 3a 22|"; startswith; pcre:"/^[a-f0-9]{16}/R"; content:"|22 2c 22|appInfos|22 3a 5b 7b 22|packageName|22 3a 22|"; fast_pattern; reference:url,www.trendmicro.com/en_us/research/23/h/mmrat-carries-out-bank-fraud-via-fake-app-stores.html; reference:md5,5b90ee49ed678379f1a8be9683b3fc99; classtype:trojan-activity; sid:2048084; rev:1; metadata:affected_product Android, attack_target Client_Endpoint, created_at 2023_09_13, deployment Perimeter, former_category MOBILE_MALWARE, malware_family MMRAT, performance_impact Low, confidence High, signature_severity Major, updated_at 2023_09_13, reviewed_at 2023_09_13; target:src_ip;)

Here is an accompanying screencap of the pcap for reference:

This rule is pretty straightforward as it is a plaintext HTTP POST request to the C2 server to the /systems/apps URI endpoint. We pay attention to the Authorization: Bearer HTTP header, as well as the “okhttp” user-agent. Then, we move the request body, in JSON format. The malware POSTS the Android Device ID, which is a 16 character hex string, followed by a complete list of applications installed on the phone.

All in all, a fairly straightforward HTTP rule, right? Well, let’s take a closer look at the CnC Checkin rules, and their corresponding traffic. Here is an ASCII dump of the stream of traffic:

Now, If you’re paying attention, you might already notice some interesting patterns here, let me further divide this data into the content I used to create the M1 and M2 CNC rules, and share some of my observations.

So, here’s the M1 CnC Checkin rule:

alert tcp $HOME_NET any -> $EXTERNAL_NET any (msg:"ET MOBILE_MALWARE Android/MMRAT CnC Checkin M1"; flow:established,to_server; content:"|01 10 03 22 10|"; offset:1; fast_pattern; pcre:"/^[a-f0-9]{16}/R"; content:"|13|20"; byte_jump:1,0, from_beginning; isdataat:!3,relative; reference:url,www.trendmicro.com/en_us/research/23/h/mmrat-carries-out-bank-fraud-via-fake-app-stores.html; reference:md5,5b90ee49ed678379f1a8be9683b3fc99; classtype:trojan-activity; sid:2048085; rev:1; metadata:affected_product Android, attack_target Client_Endpoint, created_at 2023_09_13, deployment Perimeter, former_category MOBILE_MALWARE, malware_family MMRAT, performance_impact Low, confidence High, signature_severity Major, updated_at 2023_09_13, reviewed_at 2023_09_13; target:src_ip;)

Now, let’s compare that to a hexdump of the traffic I used to create this rule:

mmrat_4

The first thing I noted in this traffic is that the first byte of data section is the length of the entire C2 packet, minus two bytes (0x90 = 144). However, the size of this C2 packet is variable, depending on the type of system sending information back to the C2 server, so we can make use of byte_jump:1,0, from_beginning; isdataat:!3,relative; to confirm the size constraints of the packet. If you want to know more about using byte_jump and isdataat, Brandon Murphy did an excellent write-up on combining the two of these rule options here.

Immediately after that I noticed that the next five bytes of the packet were consistently across at least two different samples (which, isn’t a huge sample size, buuut I worked with what I had): content:"|01 10 03 22 10|" offset:1; fast_pattern I’m not entirely sure what the hex values of the first four bytes of that content match are supposed to signify, but the final byte, 0x10 is a length field for the data that immediately comes after that content match – a 16 character hexidecimal string (in ascii format). If you take look at the POST image, that I included with data exfiltration rule, you notice that this string of letters and numbers appears to be an Android Device ID, so we can use pcre:"/^[a-f0-9]{16}/R"; to match on this string immediately after that content match.

Now, this malware transmits a ton of other data. I’ve noticed that for all the fields I could identify, the data itself is preceded by a hex value, indicating the number of bytes that particular is, and also has an additional byte appended AFTER that field whose purpose I wasn’t able to identify at this time. Let’s go over the data I was able to identify:

  • The system name (QEMU) preceded by the number of bytes (0x04)
  • The system model (StandardPC(i440FX+PIIX,1996)) preceded by the number of bytes (0x1c = 28 bytes)
    – Note: this indicates that this sample was run on a QEMU VM
  • The version of Android running on the hardware (8.1.0), in ascii format, preceded by the number of bytes (0x05)
    – Codename: Oreo
  • Android SDK/API version (27) in ascii format, preceded by the number of bytes (0x02)
  • Screen Geometry (1024x768) in ascii format, preceded by the number of bytes (0x08)
  • Timezone Designation (EST) in ascii format, preceded by the number of bytes (0x03)
  • System dialect (en_US) in ascii format, preceded by the number of bytes (0x05)
  • Datetime stamp (2023-09-11 20:21:40), preceded by the number of bytes (`0x13 = 19’)
  • Version code of the malicious application (varies – I’ve seen ascii 53 (mm.user), and ascii 10 (badoo date) used as version codes), preceded by the number of bytes (0x02)
  • Version name of the malicious application (varies – I’ve seen 1.0.9 (badoo date) and 2.1.3 (mm.user)), preceded by the number of bytes (0x05)

In one run, this was all the data transmitted in this C2 check-in, but another version (2.13/mm.user), there are another two fields, a single byte field that reads “0”, and 3-byte field that reads “dev” – perhaps indicating that developer mode is enabled? All I have is speculation here, unfortunately.

Now due to the nature of this traffic being highly variable, the only other static content I could use to create a signature here was content:"|13|20" – the very beginning of the datetime stamp, plus its size value.

Now, let’s take a look at the M2 rule:

lert tcp $HOME_NET any -> $EXTERNAL_NET any (msg:"ET MOBILE_MALWARE Android/MMRAT CnC Checkin M2"; flow:established,to_server; content:"|10|"; offset:5; pcre:"/^[a-f0-9]{16}/R"; content:"|01 01 34 90 01 01|"; fast_pattern; endswith; byte_jump:1,0, from_beginning; isdataat:!2,relative; threshold:type limit, count 1, seconds 180, track by_src; reference:url,www.trendmicro.com/en_us/research/23/h/mmrat-carries-out-bank-fraud-via-fake-app-stores.html; reference:md5,5b90ee49ed678379f1a8be9683b3fc99; classtype:trojan-activity; sid:2048086; rev:1; metadata:affected_product Android, attack_target Client_Endpoint, created_at 2023_09_13, deployment Perimeter, former_category MALWARE, malware_family MMRAT, performance_impact Low, confidence High, signature_severity Major, updated_at 2023_09_13, reviewed_at 2023_09_13; target:src_ip;)

and the corresponding dump from the packet:

mmrat_5

I wasn’t ablte to identify as much with this packet as with the M1 packet. Here are the similarities:

  • The very first byte of the payload, like the M1 packet is a size value of the entire payload, minus 1 byte. So, this allows us to use byte_check:1,0,from_beginning; isdataat:!2,relative; to confirm the size of this C2 packet.
  • 7 bytes in, there is a size value for the android Device ID field (0x10) followed by the same 16 byte hexidecimal (in ascii representation value). This allowed me to use: content:"|10|"; offset:5; pcre:"/^[a-f0-9]{16}/R"; in the rule.

The rest of the fields in this packet are a mystery to me. However, I noticed that the final six bytes of the packet – content:"|01 01 34 90 01 01|"; fast_pattern were identical in both of the packet captures I had available.

For those who want to look into this themselves, and want to know what samples I used for my analysis here are the links to the malware in virustotal:

As always, I hope this opens up additional insight. Good luck, happy hunting, and if you have corrections or thoughts you would like to add, feel free to do so – constructive criticism is always welcome!

Tony “da_667” Robinson

3 Likes