gloxec / CrossC2

generate CobaltStrike's cross-platform payload
2.21k stars 339 forks source link

CrossC2 TLS v1.3 协商问题 #87

Closed Grouppppp closed 2 years ago

Grouppppp commented 3 years ago

修改、编译 rebind 库并生成后在 Kali 上执行,提示 [error]: [parse lib]: /proc/self/fd/3: file too short!

不使用 rebind 库时会提示 conf:[alive] 但无法上线。 请问是修改的代码的问题还是生成时的问题呢。 我的 profile 中,前后字符串没有全都设置,因此在 C 代码里直接留空了,编译时无报错

gloxec commented 3 years ago

暂时尝试使用这种方式:

/tmp/c2 /tmp/c2-rebind.so

以及说下linux uname -a信息

Grouppppp commented 3 years ago

┌──(kali㉿kali)-[~/CrossC2/protocol_demo] └─$ uname -a [20:39:20] Linux kali 5.10.0-kali7-amd64 #1 SMP Debian 5.10.28-1kali1 (2021-04-12) x86_64 GNU/Linux

我尝试一下上边的方式。

Grouppppp commented 3 years ago

我在代码中修改了 cc2_rebind_http_get_recv 里 char end = ""; cc2_rebind_http_post_recv 里 char start = ""; char *end = ""; 跟这几处修改有关系吗

Grouppppp commented 3 years ago

┌──(kali㉿kali)-[~/CrossC2/protocol_demo] └─$ ./CrossC2-test ./lib_rebind_test.so [20:56:21]

┌──(kali㉿kali)-[~/CrossC2/protocol_demo] └─$ [conf]: alive [20:58:15] 按照上边的方式进行尝试,现在提示了 conf:[alive] 但在 CS 中无上线。

gloxec commented 3 years ago

出现alive代表rebind库已经正常解析,应该是你的profile与rebind库不匹配导致的,你可以查看下weblog & teamserver输出信息

Grouppppp commented 3 years ago

查看了weblog 和 teamserver 均无信息,tcpdump 抓包看了一下, Client hello 之后就 Description: Handshake Failure (40) 了。

Grouppppp commented 3 years ago

我又测试了一下不使用 rebind 库时也是 Client Hello 之后报 Handshake Failure。

Grouppppp commented 3 years ago

我用 curl 测了一下,curl 连接时的协议是TLS1.2以及TLS1.3,可以握手成功并进行数据传输,CrossC2的连接协议是 TLSv1,握手失败。 跟协议版本号是否有关?应如何解决?

Grouppppp commented 3 years ago

再次测试,使用IP不用域名的话, teamserver 提示 [-] Invalid session id [-] A Malleable C2 attempt to recover data from a '.http-get.client.metadata' transaction failed. This could be due to a bug in the profile, a change made to the profile after this Beacon was run, or a change made to the transaction by some device between your target and your Cobalt Strike controller. The following information will (hopefully) help narrow down what happened. 使用域名还是 TLS 握手失败。但检查 TLS 版本,应该也是 TLSv1.2

gloxec commented 3 years ago

[-] Invalid session id [-] A Malleable C2 attempt to recover data from a '.http-get.client.metadata' transaction failed. ..

这里的提示应当是内容已正常获取,但是profile和rebind数据解析不匹配的问题,应当检查rebind与profile的每个字段是否算法一致。

curl 连接时的协议是TLS1.2以及TLS1.3,可以握手成功并进行数据传输,CrossC2的连接协议是 TLSv1,握手失败 使用域名还是 TLS 握手失败。但检查 TLS 版本,应该也是 TLSv1.2

该问题可参考cs在win7 & 2008主机上线的问题,win7 & 2008同样使用TLS 1,该问题是因为JDK更新后将所有版本的安全策略进行了调整,禁用了TLS1&1.1 详情及解决方案: https win7

Grouppppp commented 3 years ago

关于 profile 与 rebind 匹配的问题,我研究了 demo 的 c2profile.c,发现 demo 中没有编码的操作,请问是在生成时有默认编码吗?因为我在 teamserver 里看到发出的报文是 base64 过的,但 c2profile.c 里没有 base64 的部分。如果我要修改base64url 为 base64 的话要在什么地方修改? SSL 证书问题我会修改 java 配置再测试一下。。谢谢解答

gloxec commented 3 years ago

https://gloxec.github.io/CrossC2/zh_cn/protocol/ 文档中有每个字段的详细介绍,默认传入传出的数据为base64类型,若要采用其他编码,需要自己手动对base64编码过后的数据进行解码成元数据再进行操作。

类似问题: https://github.com/gloxec/CrossC2/issues/65

Grouppppp commented 3 years ago

感谢回复。profile 与 rebind 匹配的问题我已经理解了,需要先手动解码然后操作最后重新编码发送,语言不熟悉,这个我慢慢搞。SSL 证书问题我修改了teamserver 跟 客户端机器进行尝试,然而还是握手失败。我的域名挂了 cf CDN,跟这个有关系吗?

gloxec commented 3 years ago

CDN SSL配置正确吗?在cs上host一个HTTPS类型的资源,浏览器请求CF CDN能访问到吗?

Grouppppp commented 3 years ago

经过测试,host HTTPS 类型资源是可以正常访问的。我上传并 host 了 readme,然后使用域名及 URI 访问,正常显示了内容,并能在 web log 里看到。 补充,在 web log 里看到的 IP 为 CF 地址。

gloxec commented 3 years ago

这边经过测试,CrossC2兼容了TLSv1.0 1.1 1.2,不支持1.3,且优先会从高版本开始轮询尝试协商

gloxec commented 3 years ago

临时使用了TLSv1.3的协议,你试试64位Linux能否正常通过CF呢? 如果是测试仅TLS v1.3可以的话,尝试CF端修改配置,以及后续CrossC2考虑添加此版本。 genCrossC2.Linux.zip

Grouppppp commented 3 years ago

我测试了一下,还是有问题。我把包传上来,麻烦分析一下原因。 cdn_handshake_failure.zip 压缩包内,cdn_handshake_failure 是之前的stable版本2.2.4生成的客户端抓的包,cdn_handshake_failure2 是上边链接生成的客户端抓的包。

我用 curl -v 看了一下握手过程,确实使用了 TLS v1.3。 附 curl 输出。 ┌──(kali㉿kali)-[~/CrossC2] └─$ curl -v https://domain [09:45:55]

补充,我对比了一下 curl 与 CroccC2 的 Client Hello 报文, curl 的 Extension 附加内容更多,包括 Extension: server_name (len=19) 、Extension: application_layer_protocol_negotiation (len=14) 等信息, CrossC2 的 Client Hello 包内是没有的。

gloxec commented 3 years ago

感谢提示,CF验证已通过,该问题将在下个版本中进行修复。

gloxec commented 3 years ago

@10467106 麻烦你那边测试下CF连接效果,本地这边多次测试通过 genCrossC2.Linux.zip

Grouppppp commented 3 years ago

已测试,确实能连了。。 我去处理 profile 与 rebind 匹配的问题 补充,wireshark 抓到 TLS 包了,但在 teamserver 中没看到记录,之前用 ip 测试时,即使rebind不匹配也是存在 404 访问记录的,是不是说请求依旧没有到达 teamserver 处? 测试 rebind 时发现,web 日志处确实无信息,但是上线了。 继续去研究 profile 与 rebind 的匹配。。 mask、netbios 等还没太懂怎么处理

gloxec commented 3 years ago

测试 rebind 时发现,web 日志处确实无信息,但是上线了

netbios:

  public static String encode(char paramChar, byte[] paramArrayOfbyte) {
    StringBuilder stringBuilder = new StringBuilder();
    for (byte b = 0; b < paramArrayOfbyte.length; b++) {
      int i = (paramArrayOfbyte[b] & 0xF0) >> 4;
      int j = paramArrayOfbyte[b] & 0xF;
      i += (byte)paramChar;
      j += (byte)paramChar;
      stringBuilder.append((char)i);
      stringBuilder.append((char)j);
    } 
    return stringBuilder.toString();
  }

  public static byte[] decode(char paramChar, String paramString) {
    ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
    for (byte b = 0; b < paramString.length(); b += 2) {
      char c1 = paramString.charAt(b);
      char c2 = paramString.charAt(b + 1);
      byte b1 = (byte)(c1 - (byte)paramChar << 4);
      b1 = (byte)(b1 + (byte)(c2 - (byte)paramChar));
      byteArrayOutputStream.write(b1);
    } 
    return byteArrayOutputStream.toByteArray();
  }

mask:

public static byte[] decode(byte[] paramArrayOfbyte) {
    try {
      byte[] arrayOfByte1 = new byte[paramArrayOfbyte.length - 4];
      DataParser dataParser = new DataParser(paramArrayOfbyte);
      byte[] arrayOfByte2 = dataParser.readBytes(4);
      for (byte b = 0; b < arrayOfByte1.length && dataParser.more(); b++)
        arrayOfByte1[b] = (byte)(dataParser.readByte() ^ arrayOfByte2[b % 4]); 
      return arrayOfByte1;
    } catch (Throwable throwable) {
      MudgeSanity.logException("'mask' decode [" + paramArrayOfbyte.length + " bytes] failed", throwable, false);
      return new byte[0];
    } 
  }

  public static byte[] encode(byte[] paramArrayOfbyte) {
    byte[] arrayOfByte1 = new byte[paramArrayOfbyte.length];
    byte[] arrayOfByte2 = new byte[4];
    arrayOfByte2[0] = (byte)CommonUtils.rand(255);
    arrayOfByte2[1] = (byte)CommonUtils.rand(255);
    arrayOfByte2[2] = (byte)CommonUtils.rand(255);
    arrayOfByte2[3] = (byte)CommonUtils.rand(255);
    for (byte b = 0; b < paramArrayOfbyte.length; b++)
      arrayOfByte1[b] = (byte)(paramArrayOfbyte[b] ^ arrayOfByte2[b % 4]); 
    return CommonUtils.join(arrayOfByte2, arrayOfByte1);
  }