3030 has_crypto = False
3131
3232agenttesla_sig = {
33- 'namespace1' : 'rule Agenttesla { \
33+ 'namespace1' : 'rule Agenttesla_type1 { \
3434 strings: \
35- $iestr = "C:\\ \\ Users\\ \\ Admin\\ \\ Desktop\\ \\ IELibrary\\ \\ IELibrary\\ \\ obj\\ \\ Debug\\ \\ IELibrary.pdb" \
36- $atstr = "C:\\ \\ Users\\ \\ Admin\\ \\ Desktop\\ \\ ConsoleApp1\\ \\ ConsoleApp1\\ \\ obj\\ \\ Debug\\ \\ ConsoleApp1.pdb" \
37- $sqlitestr = "Not a valid SQLite 3 Database File" wide \
35+ $type1ie = "C:\\ \\ Users\\ \\ Admin\\ \\ Desktop\\ \\ IELibrary\\ \\ IELibrary\\ \\ obj\\ \\ Debug\\ \\ IELibrary.pdb" \
36+ $type1at = "C:\\ \\ Users\\ \\ Admin\\ \\ Desktop\\ \\ ConsoleApp1\\ \\ ConsoleApp1\\ \\ obj\\ \\ Debug\\ \\ ConsoleApp1.pdb" \
37+ $type1sql = "Not a valid SQLite 3 Database File" wide \
38+ condition: all of them}' ,
39+ 'namespace2' : 'rule Agenttesla_type2 { \
40+ strings: \
41+ $type2db1 = "1.85 (Hash, version 2, native byte-order)" wide \
42+ $type2db2 = "Unknow database format" wide \
43+ $type2db3 = "SQLite format 3" wide \
3844 condition: all of them}'
3945}
4046
@@ -59,15 +65,51 @@ def get_vad_base(self, task, address):
5965
6066 return None
6167
62- def strings (self , data , n = 18 ):
68+ def base64strings (self , data , n = 18 ):
6369 for match in re .finditer (("(([0-9a-z-A-Z\+/]\x00 ){%s}([0-9a-z-A-Z\+/]\x00 )*(=\x00 ){0,2})" % n ).encode (), data ):
6470 yield match .group (0 )
6571
66- def stringdecrypt (self , a ):
72+ def remove_unascii (self , b ):
73+ cleaned = ""
74+ for i in b :
75+ if ord (i ) >= 0x20 and ord (i ) < 0x7f :
76+ cleaned += i
77+ return cleaned
78+
79+ def stringdecrypt_type1 (self , a ):
6780 string = b64decode (a )
6881 cleartext = AES .new (KEY [0 :32 ], AES .MODE_CBC , IV ).decrypt (string )
6982 return cleartext
7083
84+ def stringdecrypt_type2 (self , data ):
85+ encdata = data [0x2050 :]
86+
87+ dlist = OrderedDict ()
88+ offset = 0
89+ num = 0
90+ i = 16
91+ while True :
92+ key = encdata [offset :offset + 32 ]
93+ iv = encdata [offset + 32 :offset + 48 ]
94+ enc_data = encdata [offset + 48 :offset + 48 + i ]
95+
96+ if b"\x00 \x00 " in key and b"\x00 \x00 " in iv :
97+ break
98+
99+ try :
100+ cleartext = AES .new (key , AES .MODE_CBC , iv ).decrypt (enc_data )
101+ if len (cleartext ) and (ord (cleartext [- 1 ]) <= 0x10 or self .remove_unascii (cleartext ) % 16 == 0 ) and not (ord (cleartext [- 2 ]) == 0x0d and ord (cleartext [- 1 ]) == 0x0a ):
102+ dlist ["Encoded string " + str (num )] = self .remove_unascii (cleartext ).rstrip ()
103+ offset = offset + 48 + i
104+ num += 1
105+ i = 0
106+ else :
107+ i += 16
108+ except :
109+ i += 16
110+
111+ return dlist
112+
71113 def calculate (self ):
72114
73115 if not has_yara :
@@ -94,14 +136,18 @@ def calculate(self):
94136 data = proc_addr_space .zread (vad_base_addr , end - vad_base_addr )
95137
96138 config_data = []
97- dlist = {}
98- for word in self .strings (data ):
99- try :
100- dec = self .stringdecrypt (word )
101- dec = re .sub ("([\x00 ,\x01 ,\x02 ,\x03 ,\x04 ,\x05 ,\x06 ,\x07 ,\x08 ,\x09 ,\x0a ,\x0b ,\x0c ,\x0d ,\x0e ,\x0f ,\x10 ]{1})" , "\x00 " , dec )
102- dlist [word .strip ().replace ('\0 ' , '' )] = dec .strip ().replace ("\n " , "" ).replace ("\r " , "" )
103- except :
104- pass
139+ dlist = OrderedDict ()
140+ if "type1" in str (hit ):
141+ for word in self .base64strings (data ):
142+ try :
143+ dec = self .stringdecrypt_type1 (word )
144+ dec = self .remove_unascii (dec ).rstrip ()
145+ dlist [word .strip ().replace ('\0 ' , '' )] = dec
146+ except :
147+ pass
148+
149+ if "type2" in str (hit ):
150+ dlist = self .stringdecrypt_type2 (data )
105151
106152 config_data .append (dlist )
107153
0 commit comments