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')




