Skip to content

Commit 0ccd608

Browse files
committed
Updated QuasarRAT scan module
1 parent f390575 commit 0ccd608

File tree

2 files changed

+31
-25
lines changed

2 files changed

+31
-25
lines changed

utils/quasarscan.py

Lines changed: 28 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,9 @@
3838
quasar_sig = {
3939
'namespace1' : 'rule Quasar { \
4040
strings: \
41-
$quasarstr1 = "[PRIVATE KEY LOCATION: \\"{0}\\"]" wide \
42-
$quasarstr2 = "User: {0}{3}Pass: {1}{3}Host: {2}" wide \
43-
$quasarstr3 = "Core.MouseKeyHook.WinApi" ascii fullword \
41+
$quasarstr1 = "Client.exe" wide \
42+
$quasarstr2 = "({0}:{1}:{2})" wide \
43+
$quasarstr3 = { 52 00 65 00 73 00 6F 00 75 00 72 00 63 00 65 00 73 00 00 17 69 00 6E 00 66 00 6F 00 72 00 6D 00 61 00 74 00 69 00 6F 00 6E 00 00 80 } \
4444
condition: all of them}'
4545
}
4646

@@ -59,6 +59,8 @@
5959
8: "ENCRYPTIONKEY",
6060
9: "TAG",
6161
10: "LOGDIRECTORYNAME",
62+
11: "unknown1",
63+
12: "unknown2"
6264
}
6365

6466

@@ -76,31 +78,33 @@ def get_vad_base(self, task, address):
7678

7779
return None
7880

79-
def decrypt_string(self, key, coded):
80-
mode = AES.MODE_CBC
81-
if len(coded) < 48:
82-
value = ""
83-
else:
84-
aes_iv = coded[32:48]
85-
cipher = AES.new(key, mode, IV=aes_iv)
86-
value = cipher.decrypt(coded[48:]).replace('\x00', '').replace('\x0a', '').replace('\x0b', '')
81+
def decrypt_string(self, key, configs, mode):
82+
p_data = OrderedDict()
83+
for i, config in enumerate(configs):
84+
if i not in [2, 3, 8]:
85+
if len(b64decode(config)) < 48:
86+
value = config
87+
else:
88+
config = b64decode(config)
89+
aes_iv = config[32:48]
90+
cipher = AES.new(key, mode, IV=aes_iv)
91+
value = re.sub("[\x00-\x19]" ,"" , cipher.decrypt(config[48:]))
92+
else:
93+
value = config
94+
p_data[idx_list[i]] = value
8795

88-
return value
96+
return p_data
8997

9098
def parse_config(self, configs):
91-
i = 0
92-
p_data = OrderedDict()
9399
key, salt = configs[8], 'BFEB1E56FBCD973BB219022430A57843003D5644D21E62B9D4F180E7E6C33941'.decode('hex')
94100
generator = PBKDF2(key, salt, 50000)
95101
aes_key = generator.read(16)
96102

97-
for i, config in enumerate(configs):
98-
if i not in [2, 3, 8]:
99-
try:
100-
config = self.decrypt_string(aes_key, b64decode(config))
101-
except:
102-
pass
103-
p_data[idx_list[i]] = config
103+
if(len(configs) > 12):
104+
mode = AES.MODE_CFB
105+
else:
106+
mode = AES.MODE_CBC
107+
p_data = self.decrypt_string(aes_key, configs, mode)
104108

105109
return p_data
106110

@@ -148,13 +152,15 @@ def calculate(self):
148152
if ord(data[offset]) == 0x80 or ord(data[offset]) == 0x81:
149153
string_len = ord(data[offset + 1]) + ((ord(data[offset]) - 0x80) * 256)
150154
offset += 1
155+
151156
offset += 1
152157
for i in range(string_len):
153158
if data[offset + i] != "\x00":
154159
strings.append(data[offset + i])
155160
configs.append("".join(strings))
156161
offset = offset + string_len
157-
if len(configs) > 10:
162+
163+
if ord(data[offset]) < 0x20:
158164
break
159165

160166
config_data.append(self.parse_config(configs))

yara/rule.yara

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -474,8 +474,8 @@ rule Quasar {
474474
hash1 = "390c1530ff62d8f4eddff0ac13bc264cbf4183e7e3d6accf8f721ffc5250e724"
475475

476476
strings:
477-
$quasarstr1 = "[PRIVATE KEY LOCATION: \"{0}\"]" wide
478-
$quasarstr2 = "User: {0}{3}Pass: {1}{3}Host: {2}" wide
479-
$class = "Core.MouseKeyHook.WinApi" ascii fullword
477+
$quasarstr1 = "Client.exe" wide
478+
$quasarstr2 = "({0}:{1}:{2})" wide
479+
$class = { 52 00 65 00 73 00 6F 00 75 00 72 00 63 00 65 00 73 00 00 17 69 00 6E 00 66 00 6F 00 72 00 6D 00 61 00 74 00 69 00 6F 00 6E 00 00 80 }
480480
condition: all of them
481481
}

0 commit comments

Comments
 (0)