NET环境下的多款同源RAT对比
T0daySeeker 发表于 四川 历史精选 5848浏览 · 2024-03-01 14:11

概述

前段时间,笔者发布了一篇《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控制端,相关截图如下:

生成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
0 条评论
某人
表情
可输入 255

没有评论