Cobaltstrike是用于红队行动、apt攻击模拟的软件,它具备很强大的协同能力和难以置信的可扩展性。
无论是编写 Shellcode,创建自定义的 C2二进制可执行文件,还是修改代码来隐藏恶意程序,它们都是红队日常工作的一部分,阅读和理解成熟的C2框架代码也是理所当然的事情。
CobaltStrike是如何生成shellcode的
CS是使用Swing进行UI开发的,代码中直接找对话框对应操作类
aggressordialogsWindowsExecutableDialog.class
可以看到很清晰的生成逻辑。
protected byte[] stager;@Overridepublic void dialogAction(final ActionEvent actionEvent, final Map options) { this.options = options; this.stager = DialogUtils.getStager(options); if (this.stager.length == 0) { return; } final String string = options.get("output") + ""; String s = ""; if (string.indexOf("EXE") > -1) { s = "artifact.exe"; } else if (string.indexOf("DLL") > -1) { s = "artifact.dll"; } SafeDialogs.saveFile(null, s, this); }
通过DialogUtils.getStager()
获得生成的stager
然后通过saveFile
保存文件。
getStager()
方法调用了aggressorDataUtils.shellcode()
,而这里其实是Stagers的接口
return Stagers.shellcode(s, "x86", b);
最终在stagersStagers.shellcode()
根据监听器类型
实例化了继承自的GenericStager
的stagersGenericHTTPStager
类,并由generate()
生成shellcode
shellcode生成时,读取了resources/httpstager.bin,并根据监听器的host和port等值组合为Packer
最终替换到多个X、Y占位的bin文件中,最后返回bytes[] 类型的shellcode
Patch Artifact
shellcode生成完成后,回到原点,可以看到根据用户的选择,对不同的artifact
模板进行patch
,以x86
的模板为例
继续跟进patchArtifact
new ArtifactUtils(this.client).patchArtifact(this.stager, "artifact32.exe", s);
commonBaseArtifactUtils.class
public byte[] patchArtifact(final byte[] array, final String s) { final Stack<Scalar> stack = new Stack<Scalar>(); stack.push(SleepUtils.getScalar(array)); stack.push(SleepUtils.getScalar(s)); final String format = this.client.getScriptEngine().format("EXECUTABLE_ARTIFACT_GENERATOR", stack); if (format == null) { return this.fixChecksum(this._patchArtifact(array, s)); } return this.fixChecksum(CommonUtils.toBytes(format)); }
稍微看一下fixChecksum
,是通过PE
编辑器修复了校验码
这里不赘述了,对编辑器实现感兴趣的可以去看看pePEEditor.class
final PEEditor peEditor = new PEEditor(array); peEditor.updateChecksum();return peEditor.getImage();
注意看这里this._patchArtifact(array, s)
,调用了同名方法,PS:差点以为在看Python
读取了resources
文件夹下的artifact32.exe
作为模板文件,根据重复的1024个A
来定位shellcode
位置。
与生成shellcode时类似,使用common/CommonUtils.replaceAt()对bytes流转为的字符串进行编辑替换
public static String replaceAt(final String s, final String s2, final int n) { final StringBuffer sb = new StringBuffer(s); sb.delete(n, n + s2.length()); sb.insert(n, s2); return sb.toString(); }
使用16进制编辑器可以直接看到用于标志存放shellcode
的位置。
值得一提的是,替换shellcode之后的pe文件,因为shellcode长度没有完全覆盖到标识的1024个A,一般生成的exe都会残留部分字符,当然这并不会影响shellcode的执行
Shellcode Launcher
利用加载器远程回连获取下一阶段payload
加载到内存中执行以规避杀软的探测,这种VirtualAlloc
到WriteProcessMemory
的分配内存模式早已被众多远控木马软件广泛利用。
CS开发者在其最新的介绍视频中披露了部分artifact
的源码,并演示了如何通过修改加载器绕过了Defender
的查杀。
他通过用HeapAlloc
来代替VitualAlloc
,躲避了大部分的杀软。
在这个基础上,我们添加了对shellcode进行异或加密的功能,显然一个非常精简的基于c++的shellcode加载器就成形了。
然后参考CS的方式,在本应放置shellcode的buf中,置入大量重复的占位符作为定位。
python -c "print(1024*'A')"
用VisualStudio或MingW将其编译为template.exe
开发免杀小工具
然后新建一个JavaFx
的项目,样式与部分代码参考某chaos免杀小助手。
捋下流程,首先需要对CS或MSF的shellcode进行预处理,然后进行异或加密,读取模板文件,定位到shellcode位置,进行覆盖,最后保存。
有很多类直接可以从CS复制过来就能用。
重点看下xor,为了跟launcher解密一致,需要先转换为int类型进行异或,然后再转回hex,最终打包为jar
生成veil类型的payload,复制粘贴,生成, 保存。
最终免杀效果取决于Launcher模板,作为一个非常精简、没什么改动的模板,效果已经出乎意料了。
毕竟目的并非追求免杀效果,而应注重于理解CS木马的Artifact生成机制。