Posted on March 16, 2022 by AgeloVito@深蓝攻防实验室
0x01 场景概述
在运用CobaltStrike的过程中,经常会配合一些第三方工具,比方一些带web探测功用的工具,这些第三方工具会将获取到的webtitle或其他内容经过 beacon console > 回显给我们,而这个时分,获取到的webtitle大约率是utf-8编码格式,以至还带中文,很多时分回显是乱码的。
或者我们再来看看以下小场景,在一个简体中文的win10系统上新建两个文件,分别以utf-8和gb2312两种编码格式存储 中文+英文 的内容,gb2312.txt 和 utf-8.txt。
然后我们从 beacon console > 读取这两个文本的内容能够发现 gb2312编码的gb2312.txt文件中的中文字符显现正常,而utf-8.txt文件中的中文字符则显现乱码。
经过以上两个小场景的简单fuzz,能够得出一个初步的大约结论,该现象的缘由是由于编码不统一招致的,问题转变为哪里的编码不统一。
0x02 编码定位
要准确的定位问题所在并寻觅到比拟科学的处理计划就离不开debug,cobaltstrike属于cs架构,从MANIFEST.MF 中我们能够得知原作者的开发环境为 _1.7.080-b15 (Oracle Corporation),所以我们的反编译环境只需求大于该jdk版本即可。 client和server的代码都在同一个jar包中,因而我们需求将client端和server端的debug环境都跑起来。
1、环境搭建
整体的环境严厉来说应该分为三端,分别为 client.jar (cs运用者),server.jar(teamserver端),client.exe(被控者机器),而cobaltstike的代码量和触及到的技术含量也不少,所以最佳的选择是增量二开从而减少工作量,我们的需求只是对cs的编码问题停止改善或者加强。
反编译源代码
运用 IDEA 自带的反编译插件 java-decompiler.jar 对cobalstrike.jar先停止一次整体的反编译
java -cp java-decompiler.jar org.jetbrains.java.decompiler.main.decompiler.ConsoleDecompiler -dgs=true cs_bin/cobaltstrike.jar cs_src/
反编译全部完成后的代码会被重新打包成 cobaltstrike.jar ,将其解压就得到了我们需求的一切源代码
构建二开环境
拿到反编译后的源代码,运用 IDEA 和原始 cobalstrike.jar 就能够构建一个增量二开的环境了,过程细节不在本文中展开,可参考 @RedCore 之前的公开课。
想要修正哪局部的代码就从之前反编译完得到的代码文件中copy该到相应工程目录中停止修正,最后 Build Artifacts 即可,经过修正的代码文件就会在依赖于原始jar包的环境下被编译然后增量交换进原始的cobalstrike.jar中。
配置调试环境
配置server端
Main class 填写server端的主类
server.TeamServer
VM options 填写teamserver文件中的启动参数
-XX:ParallelGCThreads=4 -Dcobaltstrike.server_port=50050 -Djavax.net.ssl.keyStore=./cobaltstrike.store -Djavax.net.ssl.keyStorePassword=123456 -server -XX:+AggressiveHeap -XX:+UseParallelGC -classpath ./cobaltstrike.jar server.TeamServer $*
Program arguments 填写我们在运转 teamserver 时给的参数 (./teamserver 172.16.119.1 123456)
172.16.119.1 123456
ip password
在idea中以调试形式开启teamserver
配置client端
VM options 配置参数
-Dfile.encoding=UTF-8 -XX:ParallelGCThreads=4 -XX:+AggressiveHeap -XX:+UseParallelGC
server端和client端的调试环境到这里就胜利搭建起来了
2、流程剖析
每一次client.exe和server.jar的交互都会在metadata中携带当前系统编码信息,其携带的metadata将在_beacon.BeaconC2.process_beaconmetadata() 办法中调用 commcon.WindowsCharsets.getName() 将其解析为对应的编码类型的值
其中 WindowsCharsets._getName() 经过 switch case _维护了一个解析对应表
包含了简直一切的编码类型
随后在_ beaconEntry = new BeaconEntry(var6, var9, var2, var11) _处将 beaconEntry 经过带参结构函数实例化,并将编码类型值复制给 beaconEntry.chst 属性
common.BeaconEntry 会封装关于一条会话信息的一切信息供在其他业务层级的代码中流通,一些字段的含义经过命名就能猜出个八九不离十
最后在 this.getCharsets().register(beaconEntry.getId(), var9, var10) 处将编码信息停止注册
其中 register() 的完成是在 beacon.BeaconCharsets.register()
public void register(Map map, String var2, String var3) { if (var3 != null) { try { Charset var4 = Charset.forName(var3); synchronized(this) { map.put(var2, var4); } } catch (Exception var8) { MudgeSanity.logException("Could not find charset '" + var3 + "' for Beacon ID " + var2, var8, false); } } }
感谢您的来访,获取更多精彩文章请收藏本站。
1 本站一切资源不代表本站立场,并不代表本站赞同其观点和对其真实性负责。
2 本站一律禁止以任何方式发布或转载任何违法的相关信息,访客发现请向站长举报
3 本站资源大多存储在云盘,如发现链接失效,请联系我们我们会第一时间更新。
- 最新
- 最热
只看作者