PureLogs Stealer

Hi, as our collective work, I would like to present a couple of signatures for your opinion:

alert tcp any any -> any any (msg: "ET MALWARE [ANY.RUN] PureLogs Stealer Exfiltration";flow: established, to_server;content: "|C3 14 E7 23 F3 4A 30 C4 C3 14 E7 23 F3 4A 30 C4 C3 14 E7 23 F3 4A 30 C4|";threshold: type limit, track by_src, seconds 360, count 1;classtype: trojan-activity; reference: md5,2df2d284d6acb134a4af9418117c6149;  reference: url,https://app.any.run/tasks/babf3e14-a0f6-4d13-ac88-d75af6775b60; sid: 1; rev: 1;)

alert tcp any any -> any [62520]  (msg: "ET MALWARE [ANY.RUN] PureLogs Stealer C2 Connection";flow: established, to_server;stream_size: server, =, 1;stream_size: client, =, 5; dsize: 4;content: "|40 00 00 00|";depth: 4;threshold: type limit, track by_src, seconds 360, count 1;classtype: trojan-activity;reference: reference: md5,2df2d284d6acb134a4af9418117c6149;  reference: url,app.any.run/tasks/babf3e14-a0f6-4d13-ac88-d75af6775b60; sid: 2; rev: 1;)

Here is the link to the tweet:

All the best, I will continue to relax on vacation!
: ¨·.·¨ :
` ·. :butterfly:
. ^、
(˚ˎ 。7
|、˜〵
じしˍ,)ノ

1 Like

Greetings Jane,

Hope you’re enjoying your holiday. James_inthe_box reached out to me on mastodon about this, but I was a little distracted at the time, and wasn’t able to dedicate the time to discern patterns. I noticed the 30 00 00 00 and 40 00 00 00 patterns, but I had assumed that It was a size value of some sort and wouldn’t make a good sig, but 40 00 00 00 was present in the exfil frame more than once, and the packet definitely wasn’t 64 bytes in size, so there went that theory. The initial check-in packet to the server that featured the 30 00 00 00 byte pattern, I think was a size pattern. Consider that the next packet payload in the stream is 48 bytes, and that 30 00 00 00 little-endian is 48.

I came up with this rule:

alert tcp $HOME_NET any -> $EXTERNAL_NET 62520 (msg:"ET MALWARE [ANY.RUN] PureLogs Stealer C2 Connection M2"; flow:established,to_server; stream_size:client,=,53; content:"|30 00 00 00|"; fast_pattern; byte_jump:4,0, from_beginning, little, post_offset 3; isdataat:!2,relative; threshold:type limit, track by_src, seconds 360, count 1; classtype:trojan-activity; reference:md5,2df2d284d6acb134a4af9418117c6149; reference:url,app.any.run/tasks/babf3e14-a0f6-4d13-ac88-d75af6775b60; sid:1; rev:1;)

One very important caveat: Since snort doesn’t do stream reassembly on TCP traffic that is not in the stream reassembly configuration, this rule will NOT fire for snort, using its default configuration. We can, however, remove the byte_test, and set the client stream_size to 5 just like with the rule you submitted, and that does fire.

In any case, I’m rambling. Thanks for the rules, enjoy the holiday, and as usual, the rules you provided plus the one I wrote should be present in tonight’s rule release.

-Tony

2 Likes

No sooner have the rules been published than an update arrives ¯\(ツ)

What are we going to add/update? See what I think about this. The ports so far have met high ports 1024-65535. your rule for a packet of 48 bytes + 4 bytes first works on a range of ports. But just look at the detection I came up with! It is based on the fact that at the end of the exfiltered data, a 64-byte message with a header of 40 00 00 00 is embedded in the stream. Such a packet is usually far from the beginning of the stream, this packet is more than 68 bytes since another piece of data is added at the beginning of it. and it’s also worth noting that the server is silent for now. So I decided to look for such a pkt, provided that it has repeating 8 bytes in the body.

alert tcp $HOME_NET any -> $EXTERNAL_NET [1024:65535] (msg:"ET MALWARE [ANY.RUN] PureLogs Stealer C2 Connection M2";
flow:established,to_server;
stream_size:client,=,53;
content:"|30 00 00 00|"; fast_pattern;
byte_jump:4,0, from_beginning, little, post_offset 3;
isdataat:!2,relative;
threshold:type limit, track by_src, seconds 360, count 1; classtype:trojan-activity;
reference:md5,2df2d284d6acb134a4af9418117c6149;
reference:url,app.any.run/tasks/babf3e14-a0f6-4d13-ac88-d75af6775b60;
sid:1; rev:1;)

Some images here:

its about rule:
This is the rule in which the pointer moves back behind the header, to the place where there are repetitions of substrings (apparently related to encryption) of 8 bytes, extracts a variable of 4 bytes and checks in steps of 8 for a match and in steps of 7 for a non-match. I took one variable so as not to strain the sensor.

alert tcp $HOME_NET any -> $EXTERNAL_NET [1024:65535] (msg:"ET MALWARE [ANY.RUN] PureLogs Stealer Exfiltration";
flow:established,to_server, no_stream;
stream_size: server, =, 1; 
stream_size: client, >, 30000; 
dsize: >200;
content:"|40 00 00 00|"; fast_pattern; 
content: !"|0000|"; within: 64; 
isdataat:64, relative;
isdataat:!65, relative;

byte_extract: 4, -68, bytes0, relative;
byte_test: 4, =, bytes0, -76, relative;
byte_test: 4, !=, bytes0, -75, relative;

threshold:type limit, track by_src, seconds 360, count 1; classtype:trojan-activity;
reference:md5,2df2d284d6acb134a4af9418117c6149;
reference:url,app.any.run/tasks/babf3e14-a0f6-4d13-ac88-d75af6775b60;
sid:1; rev:1;)

I’m thinking about developing the detection further, I’d like your opinion.

(᎑ ᎑).zzZ
Phew, it wasn’t easy. Best regards, Jane.

2 Likes

That’s not all, sometimes it doesn’t work, here’s the version for a stream:

alert tcp $HOME_NET any -> $EXTERNAL_NET [1024:65535] (msg:"ET MALWARE [ANY.RUN] PureLogs Stealer Exfiltration (stream)";
flow:established,to_server, only_stream;
stream_size: server, <, 103;
stream_size: client, >, 30000;
content:"|40 00 00 00|"; fast_pattern;
content: !"|0000|"; within: 64;
isdataat:64, relative;
isdataat:!65, relative;

byte_extract: 4, -68, bytes0, relative;
byte_test: 4, =, bytes0, -76, relative;
byte_test: 4, !=, bytes0, -75, relative;

threshold:type limit, track by_src, seconds 360, count 1; 
classtype: trojan-activity;
reference: md5,e5b209dff3fa2fc6cd6ed434df73b8ab;
reference: url,app.any.run/tasks/9d36942e-c84e-4f92-becb-afb8289bbdf1;
sid: 2; rev: 1;)
2 Likes

Hey Jane,

Wanna let you know I’ve been looking at this rule. I took a I took a bit of time, and changed a few things from the rule you provided, but ultimately, this is what I came up with:

alert tcp-pkt $HOME_NET any -> $EXTERNAL_NET [1024:65535] (msg:"ET MALWARE [ANY.RUN] PureLogs Stealer Exfiltration"; flow:established,to_server; stream_size:client,>,30000; content:"|40 00 00 00|"; fast_pattern; content: !"|00 00|"; within: 64; isdataat:!1, relative; byte_extract: 8, -68, bytes0, relative; byte_test: 8, =, bytes0, -80, relative; threshold:type limit, track by_src, seconds 360, count 1; reference:md5,2df2d284d6acb134a4af9418117c6149; reference:url,app.any.run/tasks/babf3e14-a0f6-4d13-ac88-d75af6775b60; sid:1; rev:1;)

So… the reason this was taking so long was because I needed to compile a debug build of Suricata and enable debug messages to do some troubleshooting. One of those things is telling us what the value is of the bytes it extracted.

If any of you are playing at home and want to enable SCLogDebug messages, which show you A LOT (and I do mean A LOT) of logs for various things that Suricata is doing behind the scenes, then here is the general gist:

  1. Compile Suricata from source, with the configure argument --enable-debug. If you want to do this with my Autosuricata build script, add --enable-debug to line 239 of the script, under the configure arguments.

  2. With that done, you’ll need to set the env variable SC_LOG_LEVEL variable. On most unix-like systems, this is done with the command: export SC_LOG_LEVEL=Debug. If and when you are done with this level of debugging, you can run unset SC_LOG_LEVEL.

I know this is somewhat off-topic, but… I thought I would share the process for doing this, because while Dalton is awesome, there is no easy way to set ENV variables or collect these logs from Suricata running via Dalton.

Now, with all of that aside… Here are some changes I made:

-isdataat:64,relative and isdataat:!65,relative were kinda redundant. I’m 99% sure that the detection pointer was somehow getting set to the end of the the data stream, and therefore, we can use isdataat:!1,relative here. The alert triggers for both yesterday’s any.run sample, and the newer one you showed today.

  • I changed the byte_extract to 8 bytes. I mean, in both instances, we see an 8-byte repeating pattern, so why not try to key off the complete value?

This is the part where I had to know what value suricata was extracting from the network traffic. because I had to make sure that the negative offsets for grabbing 8 bytes of data, then hopping backwards and testing that extracted 8 bytes of data were still correct. Fun fact: 14057114478521757892 in decimal converts to C3 14 E7 23 F3 4A 30 C4 in hex. Those debug logs were how I was able to confirm that the correct offsets and values were being extracted from the stream.

  • I also opted to change the byte_test match to 8 bytes as well, and had to fix some offsets. I got rid of the negated byte_test match, because I figured with all of the rest of the rule criteria, we really don’t need a negated match to go with it.

  • I got rid of the no_stream flow option. Suricata has the tcp-pkt header option that, in this instance, is functionally similar. We can probably make use of this option for a Snort version of the rule however.

  • I got rid of the stream_size for the server side, just in case the bad guys do something dumb and change how they do server side communications. Same goes for dsize, I don’t trust the bad guys to leave their network comms consistent, so I opted to remove it entirely.

Unfortunately, due to the amount of time it took me to figure out where and how Suricata logs extracted byte values, and setting up to make it log those things, I missed the cut-off to submit new rules tonight, but I’ll likely be submitting the new version of this rule tomorrow.

In the meantime, thank you very much for your diligence and hard work, let me know your thoughts. Feel free to test out the rule I posted here, I can confirm that it triggers for both any.run sandbox run pcaps.

-Tony

1 Like

Thanks for your response. Check, rule doesn’t work here, otherwise we may encounter 126 byte packet like here.

Regarding the content mismatch check, I use negation so that I don’t encounter a null sequence before 40 00 00 00 and accidentally trigger it.

byte_extract: 8, -68, bytes0, relative;
byte_test: 8, =, bytes0, -80, relative;
byte_test: 8, !=, bytes0, -81, relative;


It is noticed that such a packet with these bytes (40 00 00 00) is exfiltrated twice in one stream.
And another strange story with isdataat, if you remove the "! "it also works 0_o
This is a link to the previous sample where the pointer has no value, either it is not equal to 1 or it is equal.

At the same place in the stream

isdataat:!1, relative;   =   isdataat:1, relative;

But If i change any value here, it won’t work, sometimes have to fuzzing the suricata))

isdataat:64, relative;              
isdataat:!65, relative;   

The miracles with the pointer continue, it is apparently only useful in combination equal to 64 and not equal to 65. So, in the stream rule it doesn’t matter !1 or 64, it still matches the same packet in the stream.

Considering the first sample in this message, I still suggest switching to the rules with a stream, using a “quantum” Schrödinger pointer (!1 = 1 superposition where he is both alive and dead) with two boundaries 64 and 65 and using 8 bytes. This happens because the stream contains a packet where condition isdataat: !1, relative is satisfied because it is of length 4, and packets where condition isdataat: 1, relative is satisfied because there are subsequent bytes. Therefore, I insist on matching exactly 64 bytes. Since there is only one such packet.

In this form, this rule works everywhere,

alert tcp $HOME_NET any -> $EXTERNAL_NET [1024:65535] (msg:"ET MALWARE [ANY.RUN] PureLogs Stealer Exfiltration (stream)";
flow:established,to_server, only_stream;

stream_size: server, <, 103;
stream_size: client, >, 30000;
content:"|40 00 00 00|"; fast_pattern;
content: !"|0000|"; within: 64;

isdataat:64, relative;
isdataat:!65, relative;

byte_extract: 8, -68, bytes0, relative;
byte_test: 8, =, bytes0, -80, relative;
byte_test: 8, !=, bytes0, -81, relative;

threshold:type limit, track by_src, seconds 360, count 1; 
classtype: trojan-activity;
reference: md5,44ae53e75958273246b11da00c75f3c9;
reference: url,app.any.run/tasks/ded1aeb9-55f5-47eb-b752-95bb288f3199;
sid: 2; rev: 1;)

Please check it, thank you very much! Don’t leave me in this confusing world of network traffic, always with you! ⋆୨୧˚

I also did the same check, but in hexes!

byte_extract: 8, -68, bytes0, relative;
byte_test: 8, =, 0xA56CF238E1B6C71B, -80, relative;

Because jumping back is like the butterfly effect, you never know what’s there)

Like here, the stream needs to be reassembled and I need to be able to jump back behind the packet. But I haven’t been able to do it yet(
https://www.joesandbox.com/analysis/897214/0/html



I check with this rule, and it doesn’t work, it’s as if I can’t get data from the stream if the content matches the beginning of the packet(

alert tcp $HOME_NET any -> $EXTERNAL_NET [1024:] (msg:"TEST PureLogs";
flow:established,to_server, only_stream;

content:"|40 00 00 00|"; fast_pattern;

byte_extract: 4, -5, bytes0, relative;
byte_test: 4, =, bytes0, -5, relative;

classtype: trojan-activity;
sid: 1; rev: 1;)

But if you step back 4 bytes, the check passes

byte_extract: 4, -4, bytes0, relative;
byte_test: 4, =, bytes0, -4, relative;

This looks like a bug, doesn’t it?

Without jumping back, the debug is as follows (https://www.joesandbox.com/analysis/897214/0/pcapslim) :

Host IP: 192.168.2.3
192.168.2.3:    49706 185.138.164.41: 7702  prt:1 sid:1.2           TEST PureLogs 
192.168.2.3:    49706 185.138.164.41: 7702  prt:1 sid:1.2           TEST PureLogs 
192.168.2.3:    49706 185.138.164.41: 7702  prt:1 sid:1.2           TEST PureLogs 
+================
TIME:              06/30/2023-19:22:29.758523
PCAP PKT NUM:      2107
PKT SRC:           wire/pcap
SRC IP:            192.168.2.3
DST IP:            185.138.164.41
PROTO:             6
SRC PORT:          49706
DST PORT:          7702
TCP SEQ:           77195529
TCP ACK:           3425879047
FLOW:              to_server: TRUE, to_client: FALSE
FLOW Start TS:     06/30/2023-19:22:19.025369
FLOW PKTS TODST:   14
FLOW PKTS TOSRC:   28
FLOW Total Bytes:  110064
FLOW IPONLY SET:   TOSERVER: TRUE, TOCLIENT: TRUE
FLOW ACTION:       DROP: FALSE
FLOW NOINSPECTION: PACKET: FALSE, PAYLOAD: FALSE, APP_LAYER: FALSE
FLOW APP_LAYER:    DETECTED: FALSE, PROTO 0
PACKET LEN:        122
PACKET:
 0000  00 0C 29 82 CB 33 EC F4  BB 86 2D ED 08 00 45 00   ..)..3.. ..-...E.
 0010  00 6C 38 06 40 00 80 06  A2 26 C0 A8 02 03 B9 8A   .l8.@... .&......
 0020  A4 29 C2 2A 1E 16 04 99  E9 09 CC 32 C4 07 50 18   .).*.... ...2..P.
 0030  FA 00 D2 2D 00 00 40 00  00 00 4A 2A 92 32 B5 8C   ...-..@. ..J*.2..
 0040  87 F3 77 C1 76 B1 D5 12  01 57 E8 B0 68 03 43 37   ..w.v... .W..h.C7
 0050  FF C1 7B CD 81 FF 25 05  D9 F3 5D 2B 04 60 D1 43   ..{...%. ..]+.`.C
 0060  8B A4 EC FF E4 54 84 AB  B7 8C 90 F7 09 58 6D 81   .....T.. .....Xm.
 0070  56 08 05 35 13 41 26 8B  4C D3                     V..5.A&. L.
ALERT CNT:           1
ALERT MSG [00]:      TEST PureLogs
ALERT GID [00]:      1
ALERT SID [00]:      2
ALERT REV [00]:      1
ALERT CLASS [00]:    A Network Trojan was detected
ALERT PRIO [00]:     1
ALERT FOUND IN [00]: STREAM
ALERT IN TX [00]:    N/A
PAYLOAD LEN:         68
PAYLOAD:
 0000  40 00 00 00 4A 2A 92 32  B5 8C 87 F3 77 C1 76 B1   @...J*.2 ....w.v.
 0010  D5 12 01 57 E8 B0 68 03  43 37 FF C1 7B CD 81 FF   ...W..h. C7..{...
 0020  25 05 D9 F3 5D 2B 04 60  D1 43 8B A4 EC FF E4 54   %...]+.` .C.....T
 0030  84 AB B7 8C 90 F7 09 58  6D 81 56 08 05 35 13 41   .......X m.V..5.A
 0040  26 8B 4C D3                                        &.L.
STREAM DATA LEN:     4
STREAM DATA:
 0000  40 00 00 00                                        @...
+================
TIME:              06/30/2023-19:22:29.995112
PCAP PKT NUM:      2113
PKT SRC:           wire/pcap
SRC IP:            192.168.2.3
DST IP:            185.138.164.41
PROTO:             6
SRC PORT:          49706
DST PORT:          7702
TCP SEQ:           77195597
TCP ACK:           3425879051
FLOW:              to_server: TRUE, to_client: FALSE
FLOW Start TS:     06/30/2023-19:22:19.025369
FLOW PKTS TODST:   15
FLOW PKTS TOSRC:   33
FLOW Total Bytes:  110398
FLOW IPONLY SET:   TOSERVER: TRUE, TOCLIENT: TRUE
FLOW ACTION:       DROP: FALSE
FLOW NOINSPECTION: PACKET: FALSE, PAYLOAD: FALSE, APP_LAYER: FALSE
FLOW APP_LAYER:    DETECTED: FALSE, PROTO 0
PACKET LEN:        60
PACKET:
 0000  00 0C 29 82 CB 33 EC F4  BB 86 2D ED 08 00 45 00   ..)..3.. ..-...E.
 0010  00 28 38 07 40 00 80 06  A2 69 C0 A8 02 03 B9 8A   .(8.@... .i......
 0020  A4 29 C2 2A 1E 16 04 99  E9 4D CC 32 C4 0B 50 10   .).*.... .M.2..P.
 0030  F9 FF 37 0F 00 00 00 00  00 00 00 00               ..7..... ....
ALERT CNT:           1
ALERT MSG [00]:      TEST PureLogs
ALERT GID [00]:      1
ALERT SID [00]:      2
ALERT REV [00]:      1
ALERT CLASS [00]:    A Network Trojan was detected
ALERT PRIO [00]:     1
ALERT FOUND IN [00]: STREAM
ALERT IN TX [00]:    N/A
STREAM DATA LEN:     4
STREAM DATA:
 0000  40 00 00 00                                        @...
STREAM DATA LEN:     68
STREAM DATA:
 0000  40 00 00 00 4A 2A 92 32  B5 8C 87 F3 77 C1 76 B1   @...J*.2 ....w.v.
 0010  D5 12 01 57 E8 B0 68 03  43 37 FF C1 7B CD 81 FF   ...W..h. C7..{...
 0020  25 05 D9 F3 5D 2B 04 60  D1 43 8B A4 EC FF E4 54   %...]+.` .C.....T
 0030  84 AB B7 8C 90 F7 09 58  6D 81 56 08 05 35 13 41   .......X m.V..5.A
 0040  26 8B 4C D3                                        &.L.
+================
TIME:              06/30/2023-19:20:31.277922
PKT SRC:           stream (flow timeout)
SRC IP:            192.168.2.3
DST IP:            185.138.164.41
PROTO:             6
SRC PORT:          49706
DST PORT:          7702
TCP SEQ:           77195597
TCP ACK:           3425879131
FLOW:              to_server: TRUE, to_client: FALSE
FLOW Start TS:     06/30/2023-19:22:19.025369
FLOW PKTS TODST:   16
FLOW PKTS TOSRC:   34
FLOW Total Bytes:  110592
FLOW IPONLY SET:   TOSERVER: TRUE, TOCLIENT: TRUE
FLOW ACTION:       DROP: FALSE
FLOW NOINSPECTION: PACKET: FALSE, PAYLOAD: FALSE, APP_LAYER: FALSE
FLOW APP_LAYER:    DETECTED: FALSE, PROTO 0
PACKET LEN:        40
PACKET:
 0000  45 00 00 28 00 00 00 00  40 06 5A 71 C0 A8 02 03   E..(.... @.Zq....
 0010  B9 8A A4 29 C2 2A 1E 16  04 99 E9 4D CC 32 C4 5B   ...).*.. ...M.2.[
 0020  50 10 0A 00 26 BF 00 00                            P...&... 
ALERT CNT:           1
ALERT MSG [00]:      TEST PureLogs
ALERT GID [00]:      1
ALERT SID [00]:      2
ALERT REV [00]:      1
ALERT CLASS [00]:    A Network Trojan was detected
ALERT PRIO [00]:     1
ALERT FOUND IN [00]: STREAM
ALERT IN TX [00]:    N/A
STREAM DATA LEN:     4
STREAM DATA:
 0000  40 00 00 00                                        @...
STREAM DATA LEN:     68
STREAM DATA:
 0000  40 00 00 00 4A 2A 92 32  B5 8C 87 F3 77 C1 76 B1   @...J*.2 ....w.v.
 0010  D5 12 01 57 E8 B0 68 03  43 37 FF C1 7B CD 81 FF   ...W..h. C7..{...
 0020  25 05 D9 F3 5D 2B 04 60  D1 43 8B A4 EC FF E4 54   %...]+.` .C.....T
 0030  84 AB B7 8C 90 F7 09 58  6D 81 56 08 05 35 13 41   .......X m.V..5.A
 0040  26 8B 4C D3                                        &.L.

Test signature:

alert tcp $HOME_NET any -> $EXTERNAL_NET [1024:] (msg:"TEST PureLogs";
flow:established,to_server, only_stream;
stream_size: server, <, 103;
stream_size: client, >, 30000;
content:"|40 00 00 00|"; fast_pattern;
content: !"|0000|"; within: 64;
isdataat:64, relative;
isdataat:!65, relative;
classtype: trojan-activity;
sid: 2; rev: 1;)

In this case, can we make a separate rule for this case? There are two rules in total - the first for the stream and the second for the packet. What do you think?

alert tcp-pkt $HOME_NET any -> $EXTERNAL_NET [1024:] (msg:"ET MALWARE [ANY.RUN] PureLogs Stealer Exfiltration M1 (pkt)";
flow:established,to_server;
stream_size: server, <, 103;
stream_size: client, >, 30000;
content:"|40 00 00 00|"; fast_pattern; depth: 4; 
content: !"|00 00|"; within: 64;
isdataat:64, relative;
isdataat:!65, relative;
threshold:type limit, track by_src, seconds 360, count 1;
reference:md5,5e6307ff0f896a11cb056cdda2d2bbdc;
reference:url,www.joesandbox.com/analysis/897214/0/html;
sid:3; rev:1;)

And for stream (I moved the byte capture deeper because I saw 64 bytes of junk bytes in the sample from Joe):

alert tcp $HOME_NET any -> $EXTERNAL_NET [1024:] (msg:"ET MALWARE [ANY.RUN] PureLogs Stealer Exfiltration M2 (stream)";
flow:established,to_server, only_stream;

stream_size: server, <, 103;
stream_size: client, >, 30000;
content:"|40 00 00 00|"; fast_pattern;
content: !"|0000|"; within: 64;

isdataat:64, relative;
isdataat:!65, relative;

byte_extract: 8, -84, bytes0, relative;
byte_test: 8, =, bytes0, -72, relative;
byte_test: 8, !=, bytes0, -71, relative;

threshold:type limit, track by_src, seconds 360, count 1; 
classtype: trojan-activity;
reference: md5,44ae53e75958273246b11da00c75f3c9;
reference: url,app.any.run/tasks/ded1aeb9-55f5-47eb-b752-95bb288f3199;
sid: 2; rev: 1;)

Hey Jane,

Thanks for the research and the rule updates. I’ve submitted both of these rules for inclusion in the ET ruleset for today. Please be aware however that for the stream reassembly rule that there is not a Snort 2.9.x version of the rule due to the requirement to manually define what TCP ports benefit from TCP stream reassembly. Because Purelogs seems to use arbitrary ports for C2, there’s no way to manually add all of the ports it could possibly use to the stream5 preprocessor.

Additionally, the |40 00 00 00| content match is not a very strong fast_pattern, and in our tests, lead to the rule getting checked quite a lot in some cases, meaning that it is going to have a significant performance impact. Therefore, we are still going to ship the rule, but our policy on most rules that have a significant performance impact is to ship them as disabled by default. So if you’re out there listening:

Purelogs Data Exfiltration Attempt M2 and M3 in the ET Ruleset will be disabled by default, and will need to be enabled for use in your environment.

As always, thank you so much for your hard work and sharing that work with the community.

-Tony

2 Likes

Hi Tony! I’m really worried about the performance hit on sensors, so let’s add a packet length prefilter to the packet rule?
dsize: 68; prefilter;
It’s okay to turn off the rules. Just wondering how the prefilter will affect performance, I don’t have the opportunity to make such an assessment?

Hi, can I ask you to add a link to this discussion in the rules 2048900 2048901 2048902?

reference:url,community.emergingthreats.net/t/purelogs-stealer/;

Updated sigs will go out today!

JT

1 Like