Post: https://twitter.com/VK_Intel/status/1152669759382654976
ServHelper: https://www.proofpoint.com/us/threat-insight/post/servhelper-and-flawedgrace-new-malware-introduced-ta505
Threat: ServHelper
Campaign ID: "ju11"
Key: "exchanger"
Xor Key: "lol"
Vigenère Key: "XMGG"
C&Cs:
- towerprod3[.]com/docs/saz.php
- lotmoji[.]com/docs/saz.php
- gdr55asf3145zadgsgsdw[.]icu/docs/saz.php
Previous ServHelper samples had all their strings unencrypted.
1.Early version example
As for the communication with the C&C observed only later versions of tunnel variant to encrypt/decrypt the request/response data with a simple xor function.
2. Xor encryption of request parameters values
In latest version of ServHelper (Campaign ju11) most of the string are encrypted with Vigenère cipher (Keys observed: XMGG, XBJB, ...)
3. Encrypted strings
IDA PRO Decryption script.
# ServHelper vigenere decrypt # @Tera0017 from idc import * from idaapi import * def prepare_string(s, alphabet): temp = s alphaList = list(alphabet) sList = list(temp) for index in range(len(sList)): for index2 in range(len(alphaList)): if temp[index] == alphaList[index2]: break if index2 + 1 == len(alphaList): sList.remove(temp[index]) final = ''.join(sList) return final def c2i(c, alphabet): return alphabet.index(c) def i2c(i, alphabet): return alphabet[i] def vigenere_decode(ciphertext, key, alphabet="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"): cipherList = list(ciphertext) keyList = list(key) alphaList = list(alphabet) decodeText = "" for index in range(len(ciphertext)): if ciphertext[index] not in alphaList: decodeText += ciphertext[index] else: cipherIndex = c2i(cipherList[index], alphabet) keyIndex = c2i((keyList[index % len(key)]), alphabet) decodeTextIndex = (cipherIndex - keyIndex) % 26 decodeText += i2c(decodeTextIndex, alphabet) return decodeText def get_string(addr): out = "" bytes2zero = 0 while True: if Byte(addr) != 0: out += chr(Byte(addr)) bytes2zero = 0 else: bytes2zero += 1 if bytes2zero == 2: break addr += 1 return out def decrypt_str(addr, KEY): print 'org:', '%08x ' % addr, addr_c = addr for i in range(5): addr = idc.PrevHead(addr) mnem = GetMnem(addr) # X86 and X64 support if ((mnem == "mov" and GetOpnd(addr, 0) == "eax" and i == 0 and 'offset' in GetOpnd(addr, 1)) or (mnem == "lea" and GetOpnd(addr, 0) == "rdx" and i == 1)): off_addr = GetOperandValue(addr, 1) encrypted = get_string(off_addr) decrypted = vigenere_decode(encrypted, KEY) print decrypted MakeComm(addr_c, decrypted) MakeComm(off_addr, decrypted) break elif i >= 1: print 'Error finding encrypted' break # TODO find vigenere function and add address + add the Key decrstr_func = 0x50f4d8 refs = [addr.frm for addr in XrefsTo(decrstr_func, flags=0)] for ref in refs: decrypt_str(ref, KEY='XMGG')