DarkCrystal RAT

Hello again!
Our good friend James found DCrat malware traffic with a new encryption layer

In turn, I quickly compared the first 344 byte check-ins and received static bytes.


Probably the rule will be further clarified, I’m working on deciphering it.
But for now I dare to propose the following solution

alert http any any -> any any (msg: "ET MALWARE [ANY.RUN] DarkCrystal Rat Check-in";flow: established, to_server; http.method; content: "POST"; http.header; content: "Content-Length: 344|0d0a|"; http.request_body;content: "|7106 785c 7908 5669 0804|"; endswith;  reference: md5,8dd1baebdcaee56ce4e4382e7071bd3d;  reference: url,app.any.run/tasks/730814fe-b061-4b67-8ff1-4455998e99f6; metadata: attack_target Client_Endpoint, deployment Perimeter, former_category MALWARE, signature_severity Major, malware_family DarkCrystal,  created_at 2023_09_15; classtype: command-and-control; sid: 1; rev: 1;)

Keep in touch, Jane

3 Likes

thanks @Jane0sint !

2048095 - ET MALWARE [ANY.RUN] DarkCrystal Rat Check-in (POST)

3 Likes

As expected, the new sample doesn’t trigger as a rule, I’m working on improving it.

I made changes to the length of the http request body, renew the 5 bytes fragments in the body (still waiting for the reverse), set the order of the headers and the php extension

alert http any any -> any any 
(msg: "ET MALWARE [ANY.RUN] DarkCrystal Rat Check-in (POST)";
flow: established, to_server; 
http.method; content: "POST"; 
http.uri; content: ".php"; endswith; 

http.content_len; 
byte_test:0,>,320,0,string,dec; 
byte_test:0,<,370,0,string,dec; 

http.request_body; 
content: "|05 06 02 01 02|";offset:8;depth:5;fast_pattern; 

http.header; 
content:"Expect|3a 20|100|2d|continue"; 

http.header_names; content: "|0d 0a|Content-Type|0d 0a|User-Agent|0d 0a|Host|0d 0a|Content-Length|0d 0a|Expect|0d 0a|Connection|0d 0a 0d 0a|"; bsize: 72; 
content:!"Referer|0d 0a|"; 
 
reference: md5,ec01cff4cf0004f1b6c934d7263f5023; 
reference: url,app.any.run/tasks/7aebaa50-c790-438c-93a5-4602f3dcefa7; 

classtype:trojan-activity; sid:2048095; rev:2; metadata:affected_product Windows_XP_Vista_7_8_10_Server_32_64_Bit, attack_target Client_Endpoint, created_at 2023_09_15, deployment Perimeter, former_category MALWARE, malware_family DCRat, confidence High, signature_severity Critical, updated_at 2023_09_15, reviewed_at 2023_09_15;)
2 Likes

I also discovered the exfiltration process via HTTP post request


2 Likes

Taking a look at updating the previous sig and the new traffic now! :smiley_cat:

2 Likes

Another launch on Windows 8

1 Like

The rule for exfiltration could be like this:

alert http any any -> any any (msg: "ET MALWARE [ANY.RUN] DarkCrystal Rat Exfiltration";
flow: established, to_server; 
http.method;content: "POST";
http.uri;content: ".php"; endswith;
http.request_body;
content: "------";  
content: "|0d 0a|Content-Disposition: form-data|3b| name=|22|0|22 0d 0a|Content-Type: text/plain|0d0a 0d0a|"; distance: 34; within: 72; 
content: "Content-Disposition: form-data|3b| name=|22|"; distance: 0;
pcre: "/^([a-f0-9]{40})\x22\x3b\x20filename=\x22\1\x22/R";
content: "|0d 0a|Content-Type: application/octet-stream|0d 0a 0d 0a|UEsD"; within: 48; http.header;
content:"Expect|3a 20|100|2d|continue";
http.header_names;
content: "|0d 0a|Content-Type|0d 0a|User-Agent|0d 0a|Host|0d 0a|Content-Length|0d 0a|Expect|0d 0a 0d 0a|";
content:!"Referer|0d 0a|";
reference: md5,ec01cff4cf0004f1b6c934d7263f5023; 
reference: url,app.any.run/tasks/79b78536-75bf-43b4-99d6-3438ba41e40c; 
classtype: trojan-activity; 
sid:1; rev:1; 
metadata:affected_product Windows_XP_Vista_7_8_10_Server_32_64_Bit, attack_target Client_Endpoint, created_at 2023_09_20, deployment Perimeter, former_category MALWARE, malware_family DCRat, confidence High, signature_severity Critical, updated_at 2023_09_20;)

Best regards, Jane ⋆⭒˚。⋆

1 Like

@Jane0sint

Nice work! One thing I was going to share is that with http.header_names you don’t need to include the negation content:!"Referer|0d 0a|"; because bsize:72; is already restricting any additional data in that buffer. I’m not sure if there is any performance impact so its fine to leave it in there but it’s not required. After updating 2048095 it alerts on the old pcap as well as the new captures. :tada:

Sid for the new signature:

2048130 - ET MALWARE [ANY.RUN] DarkCrystal Rat Exfiltration (POST)


Here are a few things I changed:

Instead of using Content-Disposition: form-data; name="0" I used pcre so that the rule will alert if any single digit name is used.

i.e. I replaced this

content: "|0d 0a|Content-Disposition: form-data|3b| name=|22|0|22 0d 0a|Content-Type: text/plain|0d0a 0d0a|";

with this:

content:"Content|2d|Disposition|3a 20|form|2d|data|3b 20|name|3d 22|"; 
pcre:"/^(?:[0-9]{1})/R"; 
content:"|22 0d 0a|Content|2d|Type|3a 20|text|2f|plain"; within:28;


I noticed in the pcap that the name/filename values were identical 40 character strings so I updated your pcre to use a named capture group. A named capture group essentially lets you store a regex match into a variable so that you can use it again without duplicating your pcre pattern.


This is the pcre that I came up with which uses the variable filename:

pcre:"/^(?P<filename>[a-z0-9]{40})\x22\x3b\x20filename\x3d\x22(?P=filename)\x22/R";

This part will match a 40 character string and store it in the variable filename

pcre:"/^(?P<filename>[a-z0-9]{40}) - matches 68c36a2defa8620c47b3f5dca991c77583292318

And this is how you can access that same value again

filename\x3d\x22(?P=filename)\x22 - which equates to filename="68c36a2defa8620c47b3f5dca991c77583292318"

Ultimately this lets us match exactly on

name="68c36a2defa8620c47b3f5dca991c77583292318"; filename="68c36a2defa8620c47b3f5dca991c77583292318"
2 Likes

Hi!
Thanks for the edit! It’s great that you write in such detail.

content: "|0d 0a|Content-Type|0d 0a|User-Agent|0d 0a|Host|0d 0a|Content-Length|0d 0a|Expect|0d 0a 0d 0a|";

The http header buffer doesn’t really allow for additional parameters, there’s just no size for anything else! I need to be more careful and not rush too much.

pcre: "/^([a-f0-9]{40})\x22\x3b\x20filename=\x22\1\x22/R";

The group in my regular expression is not named, it is called - \1 - since it is the first one.
But I agree that with a name it looks much clearer. Speed up the writing process a little by indicating the number ¯\(ツ)/¯ it’s cool that you expanded this thought into a clear expression.

Description

Named capturing groups can be used just like capturing groups — they also have their match index in the result array, and they can be referenced through \1, \2, etc. The only difference is that they can be additionally referenced by their name. The information of the capturing group’s match can be accessed through:

I’d love to hear your thoughts, Jane! ✿ڿڰۣ—

1 Like

ah I overlooked the \1 in your pcre! :man_facepalming: I actually didn’t know you could perform a back reference like that so thank for sharing that tip!

2 Likes

It’s so interesting to know that the idea to compare these parameters came to you too. You didn’t know I did it. Being in the same vibe is a thrill.⊹╰(⌣ʟ⌣)╯⊹

1 Like

Hi again! Look what we came up with on any.run, display reference links and descriptions in the threat window.


I would like to participate in the writing of both! Now the question is how to send you a description? Is there a form somewhere for submitting descriptions and links to sources?
Best wishes for the New Year! ✩₊˚.⋆☾⋆⁺₊✧
Jane.

2 Likes

Awesome! You can leave a post here of course or drop a comprehensive mail at support(at)emergingthreats(dot)net and we’ll incorporate that into our internal descriptions!

1 Like