DeCypherIT – 鸡蛋放在一个篮子里
导语:研究人员分析了一种用来封装恶意软件和隐藏恶意内容的合法服务——CypherIt。
近年来,攻击者开始使用便宜和公开提供的服务来帮助他们绕过反病毒软件的保护,以在受害者系统获取立锥之地。研究人员分析了一个类似的服务——CypherIt,该服务本身一个公开的合法服务,但被用来封装软件和隐藏恶意内容。
根据Check Point的统计数据,2019年8月到10月间通过邮件发送的恶意可执行文件有约13%使用CypherIT 这样的AutoIt crypter服务来隐藏恶意内容。
图 1 – 使用CypherIT 这样的AutoIt加密服务的恶意软件家族(2019年8月-2019年10月)
受影响的受害者的地理分布如下所示:
图 2 – AutoIt 分布(2019年8月-2019年10月)
攻击流:
图 3 – 攻击流
图 4 – 攻击流加密服务器和受害者
CypherIT是一个用来加密可执行文件的服务。其创建者声称可以绕过杀毒软件的检测,该服务在网站上公开售卖。此外,该服务还提供在系统上实现文件驻留的服务。该服务叫做packer,或者crypter。
图 5 – 来自CypherIT 官网的截图
CypherIT应用程序会发送文件到web服务——api.Cypherit[.]org,该web服务包含了所有请求的功能,如驻留、反沙箱、UAC绕过等等。
图 6 – CypherIT 包含的特征
几秒钟后,该过程就会完成,请求者就会收到一个新的文件。原始的payload使用一些增强的技术来绕过不同的安全产品。
图 7 –CypherIT 服务器
该web服务生成的新样本其实是在服务器上创建了一个嵌入了AutoIt脚本的可执行文件。而使用该服务的价格也非常低,只需要33美元(250RMB)一个月。
AutoIt和恶意软件
近期,研究人员发现在感染过程中使用AutoIt的恶意软件数量有明显的增加。AutoIt是为 Windows环境设计的脚本语言,是恶意软件开发者中常用的语言之一。脚本创建之后,就可以在脚本编译阶段创建一个单独的可执行文件。创建脚本、自动压缩和默认反调试特征的便利性使AutoIt成为恶意软件开发脚本的最好选择之一。
统计数据表明,自7月到9月间,有80%的邮件发送的恶意可执行文件使用了AutoIt;此外网络上发送的AutoIt可执行文件中有约68%是恶意用途的。
图 8 – 恶意AutoIt使用的百分比
解压和反混淆CypherIT
混淆
看到一些CypherIt生成的样本会发现其是混淆的,但CypherIt使用的都是一些基本的技术。此外,CypherIt还会持续修改混淆函数,加入一些额外的未使用的函数和条件来绕过检测。
CypherIt使用了一些功能:
· 改变字符顺序;
· 将字符串改为十六进制;
· 与固定值进行XOR操作;
· 变换字符串顺序;
· 嵌入许多非ASCII码字符。
图 9 – 逆向字符串
图 10 – 第一个参数与第二个参数的长度XOR运算
图 11 – 字符串右旋转
图 12 – BinaryToString非ASCII码字符
解压
CypherIT会是不是地修改加密方法来隐藏payload。其中最常用的3种方法是:
· 分割加密的样本,并在AutoIt脚本中进行拼接
· 分割加密的样本,将其转变成逆向十六进制字符串,并加到AutoIt 可执行文件的resources中
· 分割加密的样本,并加到AutoIt 可执行文件的resources中
下面尝试破解第三种方法。
在反混淆脚本后,可以看到一个价值可执行文件的加密资源的函数调用。该函数接收到了2个参数:
1. 用|作为分隔符的十六禁止字符串
2. Resource类型.
该函数将字符串进行分割,并按name和type加载加密的资源,然后将二进制文件连接在一起。
图 13 – 加载和连接加密的资源
下一步,CypherIT会解密payload。大多数的样本都使用AES 256算法,具体是调用以下API:
· CryptAcquireContext
· CryptCreateHash
· CryptHashData
· CryptDeriveKey
· CryptDecrypt
还有一些解密的样本是在内存中写入了含有RC4算法的shellcode。
图 14 – AES256加密
在解密payload后,CypherIT就会注入一段使用了process hollowing技术的shellcode段。Shellcode在NtOpenSection和NtMapViewOfSecion的帮助映射相关API调用来绕过hook检测。该shellcode在许多恶意软件和黑客论坛上都有出售,被称之为Frenchy shellcode。该shellcode开发者使用了mutex “Startup_shellcode_[0-9]” 或“frenchy_shellcode_[0-9]” 。
在内存中运行前,为了识别内存中的二进制文件。研究人员解压了样本,通过静态分析找到了隐藏的恶意软件payload。在解压之后,研究人员确定了恶意软件家族和类型。如下所示,解压完成后,许多杀软引擎都可以检测和识别该恶意软件。
为了获取DeCypherIT的原始PE文件:
1. 提取AutoIt 脚本的3个参数:
· Resource names
· Key
· Resource types
2. 根据字符序加载资源并连接在一起。研究人员在python中创建了一个等价的函数:
print("[+] Try to load and concatenates the resources")
resource_names_list = binascii.unhexlify(resource_names[2:]).decode("utf-8").split("|")
ciphertext, ciphertext_len = get_concatenate_resource(hfile, resource_names_list, resource_type)
print("[+] Try to decrypt the resources")
plaintext = aes_decrypt(ciphertext, ciphertext_len, key, key_len)
def get_concatenate_resource(hfile, resource_names, res_type):
concatenate_resource = 0
size = 0
for resource_name in resource_names:
h_res_info = ctypes.windll.kernel32.FindResourceW(hfile, resource_name, res_type)
if not h_res_info:
print("FindResourceW failed to find: %s resource_name" % win32api.GetLastError())
size += ctypes.windll.kernel32.SizeofResource(hfile, h_res_info)
binary_data = win32api.LoadResource(hfile, res_type, resource_name)
if concatenate_resource:
concatenate_resource += binary_data
else:
concatenate_resource = binary_data
return concatenate_resource, c_int(size)
图 15 – 加载和连接resources
3. 发送连接的resources和key到AES256
def aes_decrypt(buffer, buffer_len, key, key_len): try: # Get handle to key container hprov = c_void_p() if not windll.advapi32.CryptAcquireContextA(byref(hprov), 0, 0, PROV_RSA_AES, CRYPT_VERIFYCONTEXT): print("CryptAcquireContext failed: %s" % win32api.GetLastError()) return False # Create handle to MD5 object hHash = c_void_p() if not windll.advapi32.CryptCreateHash(hprov, CALG_MD5, 0, 0, byref(hHash)): print("CryptCreateHash failed: %s" % win32api.GetLastError()) return False # Hash the key if not windll.advapi32.CryptHashData(hHash, key, key_len, 0): print("CryptHashData failed: %s" % win32api.GetLastError()) return False # Generates AES_256 key hkey = c_void_p() if not windll.advapi32.CryptDeriveKey(hprov, CALG_AES_256, hHash, CRYPT_EXPORTABLE, byref(hkey)): print("CryptDeriveKey failed: %s" % win32api.GetLastError()) return False # Decrypts the buffer if not windll.advapi32.CryptDecrypt(hkey, 0, 1, 0, buffer, byref(buffer_len)): print("CryptDecrypt failed: %s" % win32api.GetLastError()) return False return buffer
图 16 – AES256解密
然后就获得了payload源码。
https://research.checkpoint.com/wp-content/uploads/2019/12/DeCypherIT.mp4
结论
· Packer as a Service出售者以合法服务的形式出售商品,但提供的crypter工具会被用来绕过杀毒软件的保护,并在受害者机器上实现驻留。
· Packer开发者是威胁的重要来源,因为既有官方网站,也公开提供服务。
· 经过packer 封装后,恶意软件可以绕过许多杀软引擎的检测,研究人员发现钓鱼邮件中有许多恶意软件都开始使用这种技术了。
发表评论