文章首发地址:
https://xz.aliyun.com/t/14014
文章首发作者:
T0daySeeker
概述
前段时间,笔者发布了一篇《QuasarRAT与AsyncRAT同源对比及分析》文章,文章发布后,还是获得了不少小伙伴的关注,同时还从其他渠道收到了小伙伴的私信:
首先,非常感谢大家的关注及厚爱,其次,针对小伙伴提到的内容,我准备以此为切入口详细研究对比一下。
为了能够更全面的对比分析,笔者准备从如下角度开展研究工作:
-
下载VenomRAT项目、DcRAT项目、在野DcRAT样本及在野VenomRAT样本、xRAT项目进行对比分析; -
尝试对上述样本配置信息及通信数据进行解密,并对解密算法进行对比;
通过分析,笔者发现上述VenomRAT项目、DcRAT项目、在野DcRAT样本及在野VenomRAT样本使用的配置信息加密算法均相同,以《AsyncRAT加解密技术剖析》文章中“配置信息解密”章节中描述的解密流程作为基础解密算法标准,梳理各样本针对配置信息解密算法的区别如下:
-
VenomRAT:PBKDF2算法运算中,salt字符串值为:VenomByVenom -
DcRAT:PBKDF2算法运算中,salt字符串值为:DcRatByqwqdanchun -
在野DcRAT:PBKDF2算法运算中,salt值为函数参数传入; -
在野VenomRAT样本 -
配置信息中的Key数据将用于PBKDF2算法的输入,通过迭代计算生成两个加密密钥,一个用于aes运算,密钥长度「16字节」,一个用于HMACSHA256哈希值计算,密钥长度「64字节」; -
PBKDF2算法运算中,salt十六进制值为:「BFEB1E56FBCD973BB219022430A57843003D5644D21E62B9D4F180E7E6C33941」 -
xRAT:解密算法不同 -
将key字符串的「MD5值」作为AES算法key; -
待解密字符串的前「16个字节」为AES算法的iv值,后续字节为加密数据;
VenomRAT
为了能够更好的对VenomRAT进行研究,笔者的第一想法就是看看网络中是否能够下载类似于QuasarRAT项目的具备控制端的VenomRAT程序。通过一系列网络调研,笔者确实是下载了好几个VenomRAT项目,起初还觉得很顺利,直到使用的时候,笔者才发现下载的VenomRAT项目「均携带了木马」。
为了能够继续对VenomRAT进行研究,笔者通过一系列努力,能够比较坎坷的使用VenomRAT某个版本,运行截图如下:
生成VenomRAT端木马
在GUI界面中选择【Builder】菜单即可对VenomRAT端木马进行自定义配置,支持自定义配置的内容有:
-
IP/DNS标签页:外联IP、外联端口、Pastebin、Group Name、互斥对象名 -
Startup:自启动信息、启用反虚拟机选项、禁用任务管理器选项、启用蓝屏选项 -
Assembly:属性信息、图标信息
相关截图如下:
木马上线
在受控主机中运行VenomRAT端木马程序,即可成功实现木马上线,上线后即可实现对受控主机的远控管理,相关截图如下:
配置信息解密
通过分析,笔者发现,VenomRAT端木马的反编译代码结构与AsyncRATClient端木马的反编译代码结构相同,均在Client命令空间的Settings类中存在大量的加密配置信息数据,相关截图如下:
尝试基于《AsyncRAT加解密技术剖析》文章中提到的自动化解密脚本,并对解密脚本做简单的修改,可成功对上述配置信息进行解密,解密后截图如下:
通信数据解密
对VenomRAT木马上线过程及远程控制过程进行流量抓取分析,发现其通信数据与AsyncRAT木马通信数据一致,均分为两层:
-
第一层加密:调用TLS对通信数据进行加密; -
第二层加密:调用gzip对通信载荷及传输模块进行加密;
相关截图如下:
为了进一步探究其通信模型,笔者准备从如下角度进行TLS通信解密尝试:
-
尝试基于《适用于不支持指定密钥套件的NET程序的TLS解密方法》文章中提到的修改TLS密钥套件的方法,修改其TLS通信过程中使用的密钥套件; -
尝试基于《AsyncRAT加解密技术剖析》文章中提到的私钥提取方法及通信解密方法,对VenomRAT木马TLS通信数据包进行解密;
TLS通信解密后截图如下:
通过分析,发现其TLS解密后的通信数据结构与AsyncRAT木马TLS解密后的通信数据结构极其相似,因此,尝试基于《AsyncRAT通信模型剖析及自动化解密脚本实现》文章中提供的通信解密程序对其进行批量解密,发现可成功对其进行解密,相关截图如下:
DcRAT
在对DcRAT项目的查找过程中,笔者发现也不是很顺利,因为笔者发现网络中曝光的DcRAT与github上DcRAT项目中的木马代码结构不一样,但是在进一步分析过程中,笔者发现其均使用了相同的配置信息解密算法,因此,笔者准备分别对其进行研究对比。
通过运行github上的DcRAT项目,可成功打开DcRAT控制端,相关截图如下:
在GUI界面中选择【File】->【Builder】菜单即可对DcRAT端木马进行自定义配置,支持自定义配置的内容有:
-
外联IP、外联端口、Pastebin、Group Name、互斥对象名 -
自启动信息、启用反虚拟机选项、禁用任务管理器选项、启用蓝屏选项 -
属性信息、图标信息
相关截图如下:
在受控主机中运行DcRAT端木马程序,即可成功实现木马上线,上线后即可实现对受控主机的远控管理,相关截图如下:
通过分析,笔者发现,DcRAT端木马的反编译代码结构与AsyncRATClient端木马的反编译代码结构也相同,均在Client命令空间的Settings类中存在大量的加密配置信息数据,相关截图如下:
使用相同的配置信息解密方法,并对解密脚本做简单的修改,可成功对上述配置信息进行解密,解密后截图如下:
通信数据解密
对DcRAT木马上线过程及远程控制过程进行流量抓取分析,发现其通信数据也与AsyncRAT木马通信数据一致,相关截图如下:
因此,使用相同的TLS通信数据解密方法,可成功对其TLS通信数据进行解密,解密后截图如下:
使用相同的通信解密程序对其TLS解密后通信数据进行批量解密,发现可成功对其进行解密,相关截图如下:
在野DcRAT样本剖析
为了能够全面的对DcRAT进行分析,笔者从网络中下载了一个最新曝光的DcRAT木马,相关曝光信息如下:
对其进行简单分析,笔者发现此在野DcRAT样本的反编译代码结构与DcRAT项目中的木马反编译代码结构不同,相关截图如下:
配置信息解密
进一步对其进行分析,笔者发现此样本调用的配置信息解密函数与AsyncRATClient端木马调用的配置信息解密函数相同,相关截图如下:
尝试使用相同的配置信息解密方法,并对解密脚本做简单的修改,可成功对样本中的配置信息内容进行解密,相关截图如下:
解密后的数据中还包含base64编码信息,可手动对其进行二次处理,相关操作如下:
原始字符串:
"twqziPMyOf6TnyOB/OK1jTdK956e34V42RMtGMVty6+ZbZ/0qhyPa51EFIbkOILnUmjGENz8Bsxp9j12/g0Zr3vpvrUnsOzV2cwwuEaLXKjVJIqSveHZfNuYG6F4zyNhcW8shTMg0VI7dKjnY1vGpJbwrXByPVnI4FBFnJoRImSAE1vNJjvzdOzHq5+w2xstewXQhRP4PqEtgiVd3odCEho1geLc70vkATTvkgk2FVbmSJAF1j6SSlWrBFBm8Bl2lLqol1r85lvAIjSpagTFIm8QKQfD05h5sXR17sKazsdKdP9ahYS+ldWkjEMLe8tV5boxfNV1gJDpi15NixjKJWS5myqzYOhSQn1JynlWh9ej0Y2YYlj3YEp/j+xqWYvOvnHPVdOt928Z9+jep98h0SxvkGnrNxLvcDIJI0VSVkC9eIU4XADkRe4hAMmJbvQ5671XQSoLJCsWxQ4IzS596vNXL7n+UKLx2LXD/fkJNE7NMMOKuFGBQ+IgdOffNUw9gOV3731cJ4WFYfMLMLuhZeQI4sDbY9xlAXD9Ha+7hY7Dx9sk3u9ybZZ0DP0nxW2w9zNad/GEX9+MklEXrRjLjGDD5iCQKCAMKaSVEsTvKPZ3RX2BtuRrL2egqdU531tZKbG4yJnXY12vrzJeS2Dg+1/IVQEoFVfNoWF0sPil1Dvmt28pC5+7+9v8/vIxVfn6LP4PbSpTW1qNSZK5LWQDiSAFyFfnO6Vpk7atHaYlb1+t9gBaPBOLJJQCwXLNUVhRwY271kvh8EUUwFo4ld7kPVv5zNIbe5oTVR8UewFIES2f4KGGLo4loJpBM+5dMvomDctqqFNCmASxLHikniRsOs+5ci4I0hig0khqu1JYM8hNxrlaTPI2BboP3f0gFhFN9YmTL1KicLWdh6ftKWRFQX0qPYd6Ww4oQuBAxEkKA76wEHdpoO5iDVCXoQhF+QPpXxRrxvIzbPlpmQsfPiZa+/N4P9zm0wmTv02102/UN+0="
解密后字符串:
["bj0UKX3O1fsx9BYPGXoKHqjvLayVva1jN63FIaBpzhY4ZE1D43om8NOuAFJtihcbnIkDHSHpW8UjRpWHjvb2vPk9sIFCRRHSF7QQdy5lw8PA2odUtBKwGkpYhlU9MEYF","DCR_MUTEX-11Fyfh7gXU61FzPB2sRh","0","VV??","","5","2","WyIxIiwiIiwiNSJd","WyIxIiwiV3lJaUxDSWlMQ0psZVVsM1NXcHZhV1V4VGxwVk1WSkdWRlZTVTFOV1drWm1VemxXWXpKV2VXTjVPR2xNUTBsNFNXcHZhVnB0Um5Oak1sVnBURU5KZVVscWIybGFiVVp6WXpKVmFVeERTWHBKYW05cFpFaEtNVnBUU1hOSmFsRnBUMmxLTUdOdVZteEphWGRwVGxOSk5rbHVVbmxrVjFWcFRFTkpNa2xxYjJsa1NFb3hXbE5KYzBscVkybFBhVXB0V1ZkNGVscFRTWE5KYW1kcFQybEtNR051Vm14SmFYZHBUMU5KTmtsdVVubGtWMVZwVEVOSmVFMURTVFpKYmxKNVpGZFZhVXhEU1hoTlUwazJTVzVTZVdSWFZXbE1RMGw0VFdsSk5rbHVVbmxrVjFWcFRFTkplRTE1U1RaSmJsSjVaRmRWYVV4RFNYaE9RMGsyU1c1U2VXUlhWV2xtVVQwOUlsMD0iXQ=="]
二次处理后结果:
["bj0UKX3O1fsx9BYPGXoKHqjvLayVva1jN63FIaBpzhY4ZE1D43om8NOuAFJtihcbnIkDHSHpW8UjRpWHjvb2vPk9sIFCRRHSF7QQdy5lw8PA2odUtBKwGkpYhlU9MEYF","DCR_MUTEX-11Fyfh7gXU61FzPB2sRh","0","VV??","","5","2","["1","","5"]","["1","["","","{"0":"{SYSTEMDRIVE}/Users/","1":"false","2":"false","3":"true","4":"true","5":"true","6":"true","7":"false","8":"true","9":"true","10":"true","11":"true","12":"true","13":"true","14":"true"}"]"]"]
*****************************************************************
原始字符串:
"6DuJThqLqhXMRndyjcrpSvR+NowgfgPUfadTAPLT7RzQEaQ3bZTS2B69cJ+6b9gMItPpYbJufWtQMjS77Qehab2Q+nE+hYfWDfb+T9kHg8KoSt+NAc00NmL95jbxX5qWdMKBiNsSTppEM/HD93PwYFKZCrLv7VhGHiQP8GV5/h8KKSZ+93DQTyTyXIU9kKzo6EM/bmELphag+kIO5kj28pRQY9kCOtzWU5LxezAmxJdrcp+EGjpZSgMpeynFIZE9"
解密后字符串:
["0","XPkWC3v1QKzwU0J5dAKeTsPBsYp18q5mbMsCqw5G1NTNQgIkoqWSj2GpAinnN33kONVHHGPqEEnGZBvMQFMRTmCiGDCHIS37Ts8DKAchbqOfP9P8xbXIqlQlKxBEEHhv"]
*****************************************************************
原始字符串:
zCEl5MLNt1nWGMDkINJb16lVnQwVhHlbE0ON/jzps092WYVbsn8xXBFE1kAEM8FE6Zu4vZdIFAVDmeASNmk+Cal/saaZFTYrBzpD6gHAmeV/2nzMJLz3TeS9r66FgUt0rP/vImvRIfwAfOjcSrkD1sdkzQFiIyDJZ3lO3QnF4FxspW89vlhx6OBIISdDgT0h
解密后字符串:
[["http://019214cm.nyashland.top/","EternalLineLowgameDefaultsqlbaseasyncuniversal"]]
外联通信
通过分析,发现此在野DcRAT样本的外联通信方式与DcRAT项目中的木马外联通信方式不同:
-
此在野DcRAT样本使用HTTP请求作为外联通信方式; -
DcRAT项目中的木马使用TLS作为外联通信方式;
相关截图如下:
在野VenomRAT样本剖析
为了能够全面的对VenomRAT进行分析,笔者又从网络中下载了一个VenomRAT木马,相关信息如下:
样本分析
通过分析,笔者发现此样本并非实际VenomRAT木马实体,进一步分析,笔者发现当此样本运行后,此样本将在内存中释放VenomRAT木马实体,相关截图如下:
使用de4dot对其去混淆,然后使用dnspy查看VenomRAT木马实体的反编译代码,发现VenomRAT木马实体的反编译代码与VenomRAT项目中的木马反编译代码相同,相关截图如下:
配置信息解密
使用相同的配置信息解密方法,并对解密脚本做简单的修改,可成功对上述配置信息进行解密,解密后截图如下:
xRAT
在之前的《QuasarRAT与AsyncRAT同源对比及分析》文章中,笔者曾对QuasarRAT工具的版本进行过梳理,梳理内容如下:QuasarRAT工具的早期版本名称为xRAT,xRAT于2014年7月8日发布xRAT v2.0.0.0 RELEASE1版本,后续于2015年8月23日发布Quasar v1.0.0.0版本。
通过运行github上的xRAT项目,可成功打开xRAT控制端,相关截图如下:
生成xRAT端木马
在GUI界面中选择【Builder】菜单即可对xRAT端木马进行自定义配置,支持自定义配置的内容有:
-
Connection:IP/Hostname、Port、Password、Reconnect Delay; -
Install:Mutex、Install Client选项、Install Name、Install Path、Install Subfolder、Example Path、Registry Key Name; -
Assembly Information:属性信息; -
Additional Settings:启用管理员权限选项、修改图标、启用键盘记录选项;
相关截图如下:
木马上线
在受控主机中运行xRAT端木马程序,即可成功实现木马上线,上线后即可实现对受控主机的远控管理,相关截图如下:
配置信息解密
通过分析,笔者发现,xRAT端木马的反编译代码结构与AsyncRATClient端木马的反编译代码结构也基本相同,相关截图如下:
通过对其配置信息解密算法解密分析,发现其解密算法整体逻辑相同,但还是存在多处不同点,因此,尝试修改解密算法对其进行解密,发现可成功解密,解密后截图如下:
修改后的解密脚本代码如下:
-
main.go
package main
import (
"awesomeProject3/common"
"encoding/hex"
"fmt"
"strings"
)
func main() {
file_in := "C:\Users\admin\Desktop\11.txt"
key := ""
strs := common.FileToSlice(file_in)
for _, str := range strs {
if strings.Contains(str, "public static string string_8 = ") {
key = strings.Split(strings.Split(str, ` = "`)[1], `";`)[0]
}
}
for _, str := range strs {
if strings.Contains(str, "public static string string_0 = ") {
Version := strings.Split(strings.Split(str, ` = "`)[1], `";`)[0]
fmt.Print("Version:")
decrypt_xRAT_str(key, common.Base64_Decode(Version))
} else if strings.Contains(str, "public static string string_1 = ") {
Hosts := strings.Split(strings.Split(str, ` = "`)[1], `";`)[0]
fmt.Print("Hosts:")
decrypt_xRAT_str(key, common.Base64_Decode(Hosts))
} else if strings.Contains(str, "public static string string_2 = ") {
Password := strings.Split(strings.Split(str, ` = "`)[1], `";`)[0]
fmt.Print("Password:")
decrypt_xRAT_str(key, common.Base64_Decode(Password))
} else if strings.Contains(str, "public static string string_5 = ") {
Install_Name := strings.Split(strings.Split(str, ` = "`)[1], `";`)[0]
fmt.Print("Install Name:")
decrypt_xRAT_str(key, common.Base64_Decode(Install_Name))
} else if strings.Contains(str, "public static string string_6 = ") {
Mutex := strings.Split(strings.Split(str, ` = "`)[1], `";`)[0]
fmt.Print("Mutex:")
decrypt_xRAT_str(key, common.Base64_Decode(Mutex))
}
}
}
func decrypt_xRAT_str(key string, input []byte) {
aeskey, _ := hex.DecodeString(common.CalculateMD5(key))
aes_iv := input[:16]
encode_data := input[16:]
output, _ := common.Aes_z_Decrypt(encode_data, aeskey, aes_iv)
fmt.Println(string(output))
//fmt.Println(hex.EncodeToString(output))
}
-
common.go
package common
import (
"bufio"
"crypto/aes"
"crypto/cipher"
"crypto/md5"
"encoding/base64"
"encoding/hex"
"fmt"
"os"
)
func Aes_z_Decrypt(input, key, iv []byte) (output, newiv []byte) {
output, err := aes_decrypt_cbc(input, key, iv)
//fmt.Println(hex.EncodeToString(output))
if err != nil {
panic(err)
}
newiv = append(newiv, input[len(input)-16:]...)
return
}
func aes_decrypt_cbc(data []byte, key []byte, iv []byte) ([]byte, error) {
data_new := []byte{}
data_new = append(data_new, iv...)
data_new = append(data_new, data...)
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
if len(data_new) < aes.BlockSize {
return nil, fmt.Errorf("加密数据太短")
}
iv = data_new[:aes.BlockSize]
data_new = data_new[aes.BlockSize:]
if len(data_new)%aes.BlockSize != 0 {
return nil, fmt.Errorf("加密数据长度不是块大小的整数倍")
}
mode := cipher.NewCBCDecrypter(block, iv)
mode.CryptBlocks(data_new, data_new)
data_new = pkcs5UnPadding(data_new)
return data_new, nil
}
func pkcs5UnPadding(ciphertext []byte) []byte {
length := len(ciphertext)
unpadding := int(ciphertext[length-1])
return ciphertext[:(length - unpadding)]
}
func Base64_Decode(encodedMessage string) []byte {
decodedMessage, err := base64.StdEncoding.DecodeString(encodedMessage)
if err != nil {
fmt.Println("Base64_Decode Error:", err)
return nil
}
return decodedMessage
}
func CalculateMD5(input string) string {
hasher := md5.New()
hasher.Write([]byte(input))
md5Hash := hex.EncodeToString(hasher.Sum(nil))
return md5Hash
}
func FileToSlice(file string) []string {
fil, _ := os.Open(file)
defer fil.Close()
var lines []string
scanner := bufio.NewScanner(fil)
for scanner.Scan() {
lines = append(lines, scanner.Text())
}
return lines
}
通信数据解密
对xRAT木马上线过程及远程控制过程进行流量抓取分析,发现其通信数据与其他木马的通信数据不同,xRAT木马通信数据使用socket套接字进行通信,并未使用TLS进行通信,相关截图如下:
进一步对其进行研究分析,发现其通信数据解密流程如下:
-
AES解密:将配置信息中的Password作为 decrypt_xRAT_str(key string, input []byte)
函数的key参数,将加密载荷数据作为input 参数; -
QuickLZ 解压缩:使用QuickLZ 解压算法对AES解密后的数据进行解压缩;
通信数据解密案例如下:
#通信数据载荷
300000 #载荷数据大小
8954472455a849b42094be7cba1fc9d487725502301762beee04955ded9ad8df5acd0e07dbc128545a7ce086c8552233 #加密载荷数据
#AES解密后数据
4F130000000600000000000080020000000A00
#QuickLZ解压缩后数据
020000000A00
原文始发于微信公众号(T0daySeeker):NET环境下的多款同源RAT对比