QuasarRAT与AsyncRAT同源对比及分析
T0daySeeker 发表于 四川 历史精选 11194浏览 · 2024-02-05 11:28

概述

前段时间,笔者针对AsyncRAT开源远控工具开展了一系列研究分析,从加解密技术、通信模型、攻防技术等角度发布了一系列文章,在对AsyncRAT开源远控工具进行配置信息解密的时候,笔者就一直感觉AsyncRAT反编译代码中的加密配置信息有一种似曾相识的感觉。因此,笔者就尝试查找了以前的一些资料,发现原来是QuasarRAT开源远控工具的加密配置信息与AsyncRAT开源远控工具的加密配置信息的格式很像。

为了打消疑惑,笔者尝试对QuasarRAT开源远控工具与AsyncRAT开源远控工具进行了对比分析,发现:

  • QuasarRAT开源远控工具与AsyncRAT开源远控工具使用的配置信息解密算法相同,因此其反编译代码中的加密配置信息很相似。
  • 由于QuasarRAT与AsyncRAT均是开源远控,且QuasarRAT早于AsyncRAT开源,因此,很可能是AsyncRAT在模仿学习QuasarRAT工具的配置信息加密技术。
  • 为了便于对开源远控工具进行通信模型研究,笔者在TLS通信数据解密尝试过程中,发现了一种疑似可适用于NET程序研究场景下的密钥套件自定义方法(由于笔者只是进行了简单尝试,确定当前可适用于QuasarRAT开源远控工具,但至于能否通用所有NET程序?笔者目前也不清楚,待后续研究清楚后,笔者会基于此写一篇研究分析文章供大家一起交流学习),此方法可从系统底层修改配置密钥套件,然后使用私钥对QuasarRAT的TLS通信数据进行解密。
  • 通过对TLS解密后的通信载荷进行分析,发现QuasarRAT开源远控工具与AsyncRAT开源远控工具使用的通信模型不同,QuasarRAT开源远控工具使用了protobuf序列化数据加密。

开源QuasarRAT利用分析

由于QuasarRAT开源远控工具开源时间较早,因此网络中存在不少QuasarRAT木马的攻击案例,不少APT组织均会使用此款远控木马作为最终控制程序。

网络中QuasarRAT木马利用案例如下:

进一步对QuasarRAT开源远控工具进行分析,发现:

  • 开源地址:https://github.com/quasar/Quasar
  • QuasarRAT工具的早期版本名称为xRAT,xRAT于2014年7月8日发布xRAT v2.0.0.0 RELEASE1版本,后续于2015年8月23日发布Quasar v1.0.0.0版本;
  • QuasarRAT工具的当前最新版本为2023年3月13日发布的Quasar v1.4.1版本;
  • QuasarRAT开源项目的维护人员较多,有15人维护,7900余个标星,2400余个账号forks拷贝项目;
  • QuasarRAT远控工具的所有模块均为C#代码编写,比较核心的模块为Client端、Server端、Common模块;
  • 在实际使用过程中,发现QuasarRAT远控工具在Win7环境下可能无法上线(github上说支持Win7,推测可能是.NET库不对应),建议使用Win10环境进行测试使用;

相关截图如下:

生成Client端木马

下载release版本程序并直接运行即可打开QuasarRAT控制端的GUI界面,QuasarRAT的使用逻辑与AsyncRAT的使用逻辑完全相同。

QuasarRAT控制端首次运行时,可在当前目录中生成quasar.p12文件,此文件与AsyncRAT生成的ServerCertificate.p12文件的功能相同,均是用于存放安全加密通信的密钥和证书;

在GUI界面中选择【Builder】菜单即可对Client端木马进行自定义配置,相关截图如下:

木马上线

在QuasarRAT控制端的GUI界面中选择【Settings】菜单即可开启监听,然后在受控主机中运行Client端木马程序,即可成功实现木马上线,上线后即可实现对受控主机的远控管理,相关截图如下:

与AsyncRAT同源

在对QuasarRAT进行同源对比前,需要先尝试对QuasarRAT木马进行反编译,通过分析,笔者发现:

  • QuasarRAT默认生成的Client端木马被混淆处理,若要进一步分析,需要先对木马端去混淆才能看到反编译代码;
  • 使用de4dot工具可有效的对Client端木马进行去混淆处理;

去混淆前代码截图如下:

去混淆后代码截图如下:

相同配置信息解密方法

在对QuasarRAT加密配置信息进行解密的过程中,笔者发现QuasarRAT木马与AsyncRAT木马的配置信息解密算法,除密钥生成阶段有部分不同,其余算法阶段均相同:

  • 不同点:QuasarRAT将配置信息中的密钥字符串直接作为密钥初始化的输入,AsyncRAT将配置信息中密钥字符串base64解码后的字符串作为密钥初始化的输入。
  • 相同点:其他解密代码均相同。

QuasarRAT木马配置信息截图如下:

AsyncRAT木马配置信息截图如下:

QuasarRAT木马密钥初始化代码截图如下:

AsyncRAT木马密钥初始化代码截图如下:

QuasarRAT木马解密算法截图如下:

AsyncRAT木马解密算法截图如下:

自动化解密脚本实现

由于QuasarRAT与AsyncRAT的配置信息解密算法相同,因此可直接基于笔者《AsyncRAT加解密技术剖析》文章中的配置信息解密脚本进行简单修改,即可实现QuasarRAT木马的配置信息自动化解密。

考虑到QuasarRAT木马中配置信息的命名与AsyncRAT木马的配置信息命名不同,同时,经过对比分析,发现QuasarRAT木马中配置信息字符串的顺序基本不变,因此,笔者基于QuasarRAT木马特性,又对自动化解密脚本做了定制化修改,解密效果如下:

F:\GolandProjects\awesomeProject3>awesomeProject3.exe
Version:1.4.1
Hosts:192.168.153.136:4782;
Install Subdirectory:SubDir
Install Name:Client.exe
Mutex:a76e7a42-47d0-4c26-85ca-50606b7ddae1
Startup Name:Quasar Client Startup
Client Tag:Office04
Log Directory Name:Logs
Serversignature:Bf7z8xtWtve7ucSffPkW+Xcr9w/hBPrwz7mbXwja4CNNNkBUuNisTZ0jQnI5IE+3iviHkjeF/K6ncuDRyoWrjCgjgeSi0IjzCUC9ug8a2ejYZRAW8Fru2bYBI34jO7koCUBBoowhyqnMCa1EdxZ3vhP+5Sfhkpm0fiAMW4/9XEyzoAcbNUeZW7jiNDNkkSyQnpUcX8qjtO2XNfm/5CfxqAZ3oSsY4AXSeByyOSg6z+14TI1CwdVwsg/CjDNR0e4cQcxYGLJRcWithb48KRz1DerpCajNXYU85Nd7ZqJL+lxlcBaHtfJ47DUZPhaEY0gA9OqEN3sV1PsYYrf5LAzBRxlRqlne10mL0vMgsqTA/9AoaBj+a1rLHap8pz2a9/mFhxbDVT7RPlKBCqLz627dV7SL40G1plxRSbLFYQLTUnR5GhFUll7qVTQpAB6Xr9Db0ZBDM6XvNRQittZhx4+DJpVxBiBB7MYUcDnbmngah6kgHxoxDRo0KcrXX2z134PkiRq5f+Bg4cUiqGHp9CkkZRNdzAAKgMKmKiNmRsvVfc/Hm0NZJRxG1sMnwPKTW5eJC/KLQb2KrrrUNj5E0gD+bg+P85Jsik4k6ZXoU5iT7FrYpcb+1QwxFUH5smwj0s/waTDgXZEi8D4gemUIZ8fO1k/vB0ZYINi4LWUV9Rwxcw0=
Certificate:MIIE9DCCAtygAwIBAgIQAIsBNmAKsDFbWAT7Z3kSAzANBgkqhkiG9w0BAQ0FADAbMRkwFwYDVQQDDBBRdWFzYXIgU2VydmVyIENBMCAXDTI0MDIwMjA2NDAxNFoYDzk5OTkxMjMxMjM1OTU5WjAbMRkwFwYDVQQDDBBRdWFzYXIgU2VydmVyIENBMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAhwxJ2t6TIIvmFxUgYAhkgiWTWpNt5XloFAIujZGsA2nmc2gjADu/I4/9vsL9ZkH2WZtUuWIyZNj6kciqcDLXUEs0vinaT32sVdTBmL44d5FYE2+0Qkok68faI0cDktF84B67s/WbHuRItPcBDzc/669wSBAmUjh0M+jPPLDARw6uGxafAB04BZz5e6XHp+F014rj2uUTLLTs13NACUUxyug+FmRqLljbc/sRPru7aTgsR7yEZP1/iBHTJhT56Hpujq53sKguecpVeKTdI6KjHZxKcFsM/0fOuHteWCwVqPOvHqfyoqIENSg6RKqxjrRCq2wh6u/mR8KIN9463cqgdURyVHF2B6QbmPyvj24EvkiVm1HiaBnGh1wKfAz1HsqI+w52Cj55u3UOewRBKwkBYww7qoABMuVoKk4OVEJNwF8X5FyXMc6A6jJp4h/7f9SNvD7KJwAemMJoK07JaY0o+WUcdZRQ6YKjj3knHveyxTQPa2B68ajFcskoPnAAYL5NCBQQtwctbwitD7iqwuaN7NCwVnb62hGJP+WAPaFD9viYP1JBnJMACOmAvpi8aGE2i4JxtdWXkJpuLXKlTJ42Xx3x+cs7OCdtS09AcYAUDhSdvZAhTqU7cV7Iucyd1WeJ0b6QIZZjBCLjIE4OXNy56RtPVOAa4WREZq7s67OzjVECAwEAAaMyMDAwHQYDVR0OBBYEFFtrRJmFngOkloZemoOYRn52r84vMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQENBQADggIBAHU//zXLI6lJI56CSzJKwEpd0DHVxmSWYolpEh6lVHbEirkXtIVwq42oBWOnRrWlXHTjd0XFMSh3pnpMGDly4OCoeKmo6l5BRanyW7WXpLAUSz9HNXFjkAVCNLGCt3IkRoN6C1sKRTqQmYznUyP4FxVrWuqcB96GD3Gtcd0rCEMNQrnlym3WTa9MAQSbpDgOtS2X0GiuZR6ddA39AewmgenwpS+gBXlfGXeeBiGrPptWPwD+6tXdK6UHRak/WcdFuXznNL/PN6Vy/0LWC027MIDJ69LgwkSB/jDfUlqzo3RH6Uva0odmUao49jhxtLC3Fg+JvOkMspMSE0CH0EFVdxVY/5smzYaYgniSNunYSH0aKBmMSYlBWjNsTY3/vXktgxN57hiwZPzD90AGkjx8Qcf3a9Oi8IB14EdeRxQkRT8YAiUiy5jnTEVEEdGLizF2+EGdr4LqdQthmeahfVxSv3w/bdZv8hMphHDfrlAyQKkR0toKy5cT2fb2isgefH/JRVRPkSguF7Qsy/lbY6QK8CaL9GGPqaYVKuyUgER3QDiiVMJx9Gv9+0xGJ+16H0p8EiHzkb+ki+RNmDi9a6MKNAJSQaMliVhmuWziq0N+6WdosNjHTulSBZTZAZvS7LqrHENYpyLrTHj3e8cVhpdG5cRLQk09a93I2JrZDe8MHIcX

F:\GolandProjects\awesomeProject3>

解密效果截图如下:

代码结构截图如下:(备注:common.go代码内容不变,具体代码内容请参考《AsyncRAT加解密技术剖析》文章)

  • main.go
package main

import (
    "awesomeProject3/common"
    "encoding/hex"
    "fmt"
    "strings"
)

func main() {
    key := ""

    strs := common.FileToSlice("C:\\Users\\admin\\Desktop\\11.txt")
    for _, str := range strs {
        if strings.Contains(str, "public static string string_7 = ") {
            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_QuasarRAT_str(key, Version)
        } else if strings.Contains(str, "public static string string_1 = ") {
            Hosts := strings.Split(strings.Split(str, ` = "`)[1], `";`)[0]
            fmt.Print("Hosts:")
            decrypt_QuasarRAT_str(key, Hosts)
        } else if strings.Contains(str, "public static string string_3 = ") {
            Install_Subdirectory := strings.Split(strings.Split(str, ` = "`)[1], `";`)[0]
            fmt.Print("Install Subdirectory:")
            decrypt_QuasarRAT_str(key, Install_Subdirectory)
        } else if strings.Contains(str, "public static string string_4 = ") {
            Install_Name := strings.Split(strings.Split(str, ` = "`)[1], `";`)[0]
            fmt.Print("Install Name:")
            decrypt_QuasarRAT_str(key, Install_Name)
        } else if strings.Contains(str, "public static string string_5 = ") {
            Mutex := strings.Split(strings.Split(str, ` = "`)[1], `";`)[0]
            fmt.Print("Mutex:")
            decrypt_QuasarRAT_str(key, Mutex)
        } else if strings.Contains(str, "public static string string_6 = ") {
            Startup_Name := strings.Split(strings.Split(str, ` = "`)[1], `";`)[0]
            fmt.Print("Startup Name:")
            decrypt_QuasarRAT_str(key, Startup_Name)
        } else if strings.Contains(str, "public static string string_8 = ") {
            Client_Tag := strings.Split(strings.Split(str, ` = "`)[1], `";`)[0]
            fmt.Print("Client Tag:")
            decrypt_QuasarRAT_str(key, Client_Tag)
        } else if strings.Contains(str, "public static string string_9 = ") {
            Log_Directory_Name := strings.Split(strings.Split(str, ` = "`)[1], `";`)[0]
            fmt.Print("Log Directory Name:")
            decrypt_QuasarRAT_str(key, Log_Directory_Name)
        } else if strings.Contains(str, "public static string string_10 = ") {
            Serversignature := strings.Split(strings.Split(str, ` = "`)[1], `";`)[0]
            fmt.Print("Serversignature:")
            decrypt_QuasarRAT_str(key, Serversignature)
        } else if strings.Contains(str, "public static string string_11 = ") {
            Certificate := strings.Split(strings.Split(str, ` = "`)[1], `";`)[0]
            fmt.Print("Certificate:")
            decrypt_QuasarRAT_str(key, Certificate)
        }
    }
}

func decrypt_QuasarRAT_str(key string, input_str string) {
    input := common.Base64_Decode(input_str)
    hmacsha := input[:32]
    aes_iv := input[32:48]
    encode_data := input[48:]

    //代码不同
    rfc2898DeriveBytes := common.Pbkdf2_Rfc2898DeriveBytes([]byte(key))
    //fmt.Println(hex.EncodeToString(rfc2898DeriveBytes))
    aeskey := rfc2898DeriveBytes[:32]
    _authKey := rfc2898DeriveBytes[32:]

    if hex.EncodeToString(common.HMACSHA256(_authKey, input[32:])) != hex.EncodeToString(hmacsha) {
        fmt.Println("Error")
        return
    }
    output, _ := common.Aes_decrypt_cbc(encode_data, aeskey, aes_iv)
    fmt.Println(string(output))
}

通信数据解密对比

对QuasarRAT木马上线过程及远程控制过程进行流量抓取分析,发现其通信数据主要分为两层:

  • 第一层加密:调用TLS1.2对通信数据进行加密,密钥套件带DH算法;
  • 第二层加密:调用protobuf序列化对通信载荷进行加密;

相关截图如下:

TLS解密

由于必须成功解密最外层TLS通信数据才能对底层通信载荷进行详细的对比研究,因此,笔者花了不少时间对其进行琢磨研究,最终发现了一种疑似可适用于NET程序研究场景下的密钥套件自定义方法,通过自定义密钥套件配置,笔者可成功基于私钥对最外层TLS通信数据进行解密。

备注:私钥提取过程可参考《AsyncRAT加解密技术剖析》文章“TLS解密-私钥提取”章节。

相关截图如下:

TLS解密后数据载荷截图如下:

反序列化通信数据

成功解密TLS通信数据后,即可对底层通信数据进行分析,通过动态调试及对比分析,笔者发现TLS解密后的通信载荷为protobuf序列化数据。

相关protobuf序列化调用dll截图如下:

相关调用代码截图如下:

解密数据包截图如下:(解密数据包中的载荷数据与调用代码中的载荷数据相同)

为了能够有效的对protobuf序列化数据进行反序列化,笔者进行了多种尝试(编写C#脚本、编写golang脚本、使用在线工具等),最终,笔者找到了一种比较便捷的方法,即使用CyberChef在线平台解密protobuf序列化数据。

在线工具解密截图如下:

解密效果如下:

{
    "37": {
        "1": [
            {
                "1": "svchost",
                "2": "0.0.0.0",
                "3": 135,
                "4": "0.0.0.0",
                "6": 2
            },
            {
                "1": "System",
                "2": "0.0.0.0",
                "3": 445,
                "4": "0.0.0.0",
                "6": 2
            },
            {
                "1": "svchost",
                "2": "0.0.0.0",
                "3": 5040,
                "4": "0.0.0.0",
                "6": 2
            },
            {
                "1": "svchost",
                "2": "0.0.0.0",
                "3": 7680,
                "4": "0.0.0.0",
                "6": 2
            },
            {
                "1": "lsass",
                "2": "0.0.0.0",
                "3": 49664,
                "4": "0.0.0.0",
                "6": 2
            },
            {
                "1": "wininit",
                "2": "0.0.0.0",
                "3": 49665,
                "4": "0.0.0.0",
                "6": 2
            },
            {
                "1": "svchost",
                "2": "0.0.0.0",
                "3": 49666,
                "4": "0.0.0.0",
                "6": 2
            },
            {
                "1": "svchost",
                "2": "0.0.0.0",
                "3": 49667,
                "4": "0.0.0.0",
                "6": 2
            },
            {
                "1": "spoolsv",
                "2": "0.0.0.0",
                "3": 49668,
                "4": "0.0.0.0",
                "6": 2
            },
            {
                "1": "services",
                "2": "0.0.0.0",
                "3": 49669,
                "4": "0.0.0.0",
                "6": 2
            },
            {
                "1": "HipsDaemon",
                "2": {
                    "6": 3543822931722123300
                },
                "3": 53730,
                "4": "0.0.0.0",
                "6": 2
            },
            {
                "1": "System",
                "2": "192.168.153.135",
                "3": 139,
                "4": "0.0.0.0",
                "6": 2
            },
            {
                "1": "Client-built",
                "2": "192.168.153.135",
                "3": 49857,
                "4": "192.168.153.136",
                "5": 4782,
                "6": 5
            }
        ]
    }
}

对应QuasarRAT控制端GUI界面截图如下:

使用在线平台CyberChef解密protobuf序列化数据的案例网页地址如下:

#使用CyberChef在线平台解密protobuf序列化数据的案例网页地址

https://gchq.github.io/CyberChef/#recipe=From_Hex('Auto')Protobuf_Decode('',false,false)&input=YWEwMmU0MDMwYTIwMGEwNzczNzY2MzY4NmY3Mzc0MTIwNzMwMmUzMDJlMzAyZTMwMTg4NzAxMjIwNzMwMmUzMDJlMzAyZTMwMzAwMjBhMWYwYTA2NTM3OTczNzQ2NTZkMTIwNzMwMmUzMDJlMzAyZTMwMThiZDAzMjIwNzMwMmUzMDJlMzAyZTMwMzAwMjBhMjAwYTA3NzM3NjYzNjg2ZjczNzQxMjA3MzAyZTMwMmUzMDJlMzAxOGIwMjcyMjA3MzAyZTMwMmUzMDJlMzAzMDAyMGEyMDBhMDc3Mzc2NjM2ODZmNzM3NDEyMDczMDJlMzAyZTMwMmUzMDE4ODAzYzIyMDczMDJlMzAyZTMwMmUzMDMwMDIwYTFmMGEwNTZjNzM2MTczNzMxMjA3MzAyZTMwMmUzMDJlMzAxODgwODQwMzIyMDczMDJlMzAyZTMwMmUzMDMwMDIwYTIxMGEwNzc3Njk2ZTY5NmU2OTc0MTIwNzMwMmUzMDJlMzAyZTMwMTg4MTg0MDMyMjA3MzAyZTMwMmUzMDJlMzAzMDAyMGEyMTBhMDc3Mzc2NjM2ODZmNzM3NDEyMDczMDJlMzAyZTMwMmUzMDE4ODI4NDAzMjIwNzMwMmUzMDJlMzAyZTMwMzAwMjBhMjEwYTA3NzM3NjYzNjg2ZjczNzQxMjA3MzAyZTMwMmUzMDJlMzAxODgzODQwMzIyMDczMDJlMzAyZTMwMmUzMDMwMDIwYTIxMGEwNzczNzA2ZjZmNmM3Mzc2MTIwNzMwMmUzMDJlMzAyZTMwMTg4NDg0MDMyMjA3MzAyZTMwMmUzMDJlMzAzMDAyMGEyMjBhMDg3MzY1NzI3NjY5NjM2NTczMTIwNzMwMmUzMDJlMzAyZTMwMTg4NTg0MDMyMjA3MzAyZTMwMmUzMDJlMzAzMDAyMGEyNjBhMGE0ODY5NzA3MzQ0NjE2NTZkNmY2ZTEyMDkzMTMyMzcyZTMwMmUzMDJlMzExOGUyYTMwMzIyMDczMDJlMzAyZTMwMmUzMDMwMDIwYTI3MGEwNjUzNzk3Mzc0NjU2ZDEyMGYzMTM5MzIyZTMxMzYzODJlMzEzNTMzMmUzMTMzMzUxODhiMDEyMjA3MzAyZTMwMmUzMDJlMzAzMDAyMGEzOTBhMGM0MzZjNjk2NTZlNzQyZDYyNzU2OTZjNzQxMjBmMzEzOTMyMmUzMTM2MzgyZTMxMzUzMzJlMzEzMzM1MThjMTg1MDMyMjBmMzEzOTMyMmUzMTM2MzgyZTMxMzUzMzJlMzEzMzM2MjhhZTI1MzAwNQ
0 条评论
某人
表情
可输入 255