Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CrossC2 TLS v1.3 协商问题 #87

Closed
Grouppppp opened this issue Jun 10, 2021 · 22 comments
Closed

CrossC2 TLS v1.3 协商问题 #87

Grouppppp opened this issue Jun 10, 2021 · 22 comments
Labels

Comments

@Grouppppp
Copy link

Grouppppp commented Jun 10, 2021

修改、编译 rebind 库并生成后在 Kali 上执行,提示
[error]: [parse lib]: /proc/self/fd/3: file too short!
[error]: [parse symbol]: (null)!
不使用 rebind 库时会提示 conf:[alive] 但无法上线。
请问是修改的代码的问题还是生成时的问题呢。
我的 profile 中,前后字符串没有全都设置,因此在 C 代码里直接留空了,编译时无报错

@Grouppppp Grouppppp changed the title CS4.3 + Kali 提示 paese llib error CS4.3 + Kali 提示 parse llib error Jun 10, 2021
@Grouppppp Grouppppp changed the title CS4.3 + Kali 提示 parse llib error CS4.3 + Kali 提示 parse lib error Jun 10, 2021
@gloxec
Copy link
Owner

gloxec commented Jun 10, 2021

暂时尝试使用这种方式:

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

以及说下linux uname -a信息

@Grouppppp
Copy link
Author

┌──(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
Copy link
Author

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

@Grouppppp
Copy link
Author

┌──(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
Copy link
Owner

gloxec commented Jun 10, 2021

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

@Grouppppp
Copy link
Author

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

@Grouppppp
Copy link
Author

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

@Grouppppp
Copy link
Author

Grouppppp commented Jun 11, 2021

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

@Grouppppp
Copy link
Author

再次测试,使用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
Copy link
Owner

gloxec commented Jun 12, 2021

[-] 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
Copy link
Author

Grouppppp commented Jun 12, 2021

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

@gloxec
Copy link
Owner

gloxec commented Jun 14, 2021

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

类似问题: #65

@Grouppppp
Copy link
Author

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

@gloxec
Copy link
Owner

gloxec commented Jun 19, 2021

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

@Grouppppp
Copy link
Author

Grouppppp commented Jun 24, 2021

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

@gloxec
Copy link
Owner

gloxec commented Jun 28, 2021

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

@gloxec
Copy link
Owner

gloxec commented Jun 29, 2021

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

@gloxec gloxec changed the title CS4.3 + Kali 提示 parse lib error CrossC2 TLS v1.3 协商问题 Jun 29, 2021
@gloxec gloxec added the New label Jun 29, 2021
@Grouppppp
Copy link
Author

Grouppppp commented Jun 30, 2021

我测试了一下,还是有问题。我把包传上来,麻烦分析一下原因。
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]

  • Trying 104.21.27.229:443...
  • Connected to domain (104.21.27.229) port 443 (#0)
  • ALPN, offering h2
  • ALPN, offering http/1.1
  • successfully set certificate verify locations:
  • CAfile: /etc/ssl/certs/ca-certificates.crt
  • CApath: /etc/ssl/certs
  • TLSv1.3 (OUT), TLS handshake, Client hello (1):
  • TLSv1.3 (IN), TLS handshake, Server hello (2):
  • TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
  • TLSv1.3 (IN), TLS handshake, Certificate (11):
  • TLSv1.3 (IN), TLS handshake, CERT verify (15):
  • TLSv1.3 (IN), TLS handshake, Finished (20):
  • TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
  • TLSv1.3 (OUT), TLS handshake, Finished (20):
  • SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384
  • ALPN, server accepted to use h2
  • Server certificate:
  • subject: CN=*.domain
  • start date: May 18 06:48:03 2021 GMT
  • expire date: Aug 16 06:48:03 2021 GMT
  • subjectAltName: host "domain " matched cert's "*.domain "
  • issuer: C=US; O=Let's Encrypt; CN=R3
  • SSL certificate verify ok.
  • Using HTTP2, server supports multi-use
  • Connection state changed (HTTP/2 confirmed)
  • Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
  • Using Stream ID: 1 (easy handle 0x55bd401c8490)

GET / HTTP/2
Host: domain
user-agent: curl/7.74.0
accept: /

  • TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
  • TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
  • old SSL session ID is stale, removing
  • Connection state changed (MAX_CONCURRENT_STREAMS == 256)!
    < HTTP/2 404
    < date: Wed, 30 Jun 2021 01:46:19 GMT
    < content-type: text/plain
    < content-length: 0
    < cf-cache-status: DYNAMIC
    < cf-request-id: 0afc318f000000d34a2e228000000001
    以下略

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

@gloxec
Copy link
Owner

gloxec commented Jul 1, 2021

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

@gloxec
Copy link
Owner

gloxec commented Jul 1, 2021

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

@Grouppppp
Copy link
Author

Grouppppp commented Jul 6, 2021

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

@gloxec
Copy link
Owner

gloxec commented Jul 16, 2021

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

  • 普通的http/https 包在weblog界面处会记录
  • cs通信结构的http/https包不会被记录
  • cs通信结构但无法正常解析的http/https包在teamserver处会显示

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);
  }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants