標題:破解CobaltStrike3.12(轉)

taibeihacker

Moderator

0x00 概述​

CobaltStrike是一款內網滲透的商業遠控軟件,支持自定義腳本擴展,功能非常強大。前段時間Github上有好心人放出了CobaltStrike3.12的試用版,接著Lz1y很快就放出了破解版,加上熱心老哥提供了的xor64.bin(試用版中沒有這個文件),一個比較完美的最新可用版本誕生了。下面我們看下最新試用版是如何被完美破解的。

0x02 上手​

CobaltStrike(下面簡稱CS)主體代碼是用Java開發的,逆起來比較友好。用jd-gui反編譯cobaltstrike.jar文件,可以看到代碼幾乎沒有做防破解。 Java源碼沒有任何混淆。但是查看反編譯的源碼時,很多地方出現了//INTERNAL ERROR //,這裡我推荐一款Java反編譯工具luyten,幾乎可以100%反編譯獲得cobaltstrike.jar源碼。
CS的License處理邏輯在common/License.java文件中:
package common;
import aggressor.*;
import javax.swing.*;
import java.awt.*;
public class License
{
private static long life;
private static long today;
private static long start;
private static long difference;
private static long getTimeSinceStart() {
final Prefs options=Prefs.getPreferences();
License.today=System.currentTimeMillis();
License.start=options.getLongNumber('cobaltstrike.start.int', 0L);
if (License.start==0L) {
options.set('cobaltstrike.start.int', License.today + '');
options.save();
License.start=License.today;
}
return License.difference=(License.today - License.start)/86400000L;
}
public static void checkLicenseGUI(final Authorization auth) {
getTimeSinceStart();
if (License.difference License.life || License.today - License.start 0L) {
JOptionPane.showMessageDialog(null, 'Your Cobalt Strike trial is now expired.\nPlease purchase a license and use the\nsoftware update feature to continue.\n\nFor details, visit:\nhttps://www.cobaltstrike.com/', null, 0);
System.exit(0);
}
else {
final long left=License.life - License.difference;
String form=left + ' day';
if (left !=1L) {
form +='s';
}
CommonUtils.print_warn('This is a trial version of Cobalt Strike. You have ' + form + ' left of your trial. If you purchased Cobalt Strike. Run the Update program and enter your license.');
CommonUtils.print_trial('WARNING! This trial is *built* to get caught by standard defenses. The licensed product does not have these restrictions. See: http://blog.cobaltstrike.com/2015/10/14/the-cobalt-strike-trials-evil-bit/');
JOptionPane.showMessageDialog(null, 'This is a trial version of Cobalt Strike.\nYou have ' + form + ' left of your trial.\n\nIf you purchased Cobalt Strike. Run the\nUpdate program and enter your license.', null, 1);
}
}
public static boolean isTrial() {
return true;
}
public static void checkLicenseConsole(final Authorization auth) {
getTimeSinceStart();
if (License.difference License.life || License.today - License.start 0L) {
CommonUtils.print_error('Your Cobalt Strike trial is now expired. Please purchase a license and use the software update feature to continue. For details, visit: https://www.cobaltstrike.com/');
System.exit(0);
}
else {
final long left=License.life - License.difference;
String form=left + ' day';
if (left !=1L) {
form +='s';
}
CommonUtils.print_warn('This is a trial version of Cobalt Strike. You have ' + form + ' left of your trial. If you purchased Cobalt Strike. Run the Update program and enter your license.');
CommonUtils.print_trial('WARNING! This trial is *built* to get caught by standard defenses. The licensed product does not have these restrictions. See: http://blog.cobaltstrike.com/2015/10/14/the-cobalt-strike-trials-evil-bit/');
}
}
static {
License.life=21L;
License.today=0L;
License.start=0L;
License.difference=0L;
}
}
代碼邏輯很清晰,這裡我們有兩個方向進行patch:
修改License.life無限延長試用
修改isTrial()返回值,偽造成正式版
因為CS很多地方的試用版和正式版處理邏輯不同,所以修改了isTrial()返回值之後,我們還需要修改所有調用了isTrial()函數的地方,對代碼進行調整。另外試用版CS留了一些特徵指紋和限制,我們也需要去除相應的特征代碼。
修改重打包既然知道了破解思路,我們看下如何動手操作去修改源碼並重編譯。 Java編程中我們可以使用jar工具將一系列的.class文件打包成jar包,供其他java程序使用。我們也可以修改jar包中.class文件的內容,並重新編譯打包。比如修改demo.jar中的example.class並重新編譯的過程如下:
使用jd-gui、luyten等工具把demo.jar包中的class反編譯成源碼,從中提取得到example.java
執行jar xvf demo.jar解壓demo.jar得到jar包的子文件(注意會解壓到當前目錄),將example.java文件放置到與example.class文件同一目錄
執行javac -cp a.jar;b.jar;c.jar example.java重新編譯。 (或者javac -cp demo.jar example.java)得到新的example.class文件。
其中a.jar、b.jar、c.jar是依賴包,一般直接依賴一個原始解壓的demo.jar包即可
確保編譯後的example.class替換了原來的example.class文件(可以通過jd-gui反編譯查看)
執行jar -uvf demo.jar com/some/path/example.class更新demo.jar包
更新jar包中的class文件時,新的class文件目錄路徑需要與原package路徑保持一致。比如修改了aggressor.AggressorClient.java並重新編譯之後,更新jar包的命令如下:
KINGX modified_java_files jar -uvf cobaltstrike-with-xor64.jar aggressor/AggressorClient*.class
正在添加: aggressor/AggressorClient$1.class(輸入=650) (輸出=403)(壓縮了38%)
正在添加: aggressor/AggressorClient$2.class(輸入=1263) (輸出=704)(壓縮了44%)
正在添加: aggressor/AggressorClient.class(輸入=11115) (輸出=5196)(壓縮了53%)
可能遇到的问题修改後的java文件在重新編譯為class文件時,可能會遇到很多奇怪的報錯。有時候是因為反編譯出的源碼存在錯誤導致的,這個時候我們可以將luyten、jad、jd-gui等反編譯工具結合使用,盡量還原成正確的源碼,再重新編譯。 比如:AggressorClient.java,jad aggressor/AggressorClient*.class和luyten反編譯得到的源碼是不一樣的。

0x03 试用版Patch详细分析​

Tips: 以下代碼片段中行首的- 代表刪除,+ 代表新增
Patch 试用版本修改common.License,去掉checkLicenseGUI()、checkLicenseConsole()函數體,修改isTrial()返回值為true
修改主程序标题aggressor.AggressorClient,修改getTitle()函數
解除listener同类数量限制一個teamserver默認只能監聽一個listener,可以通過修改代碼去除限制。
aggressor.dialogs.ListenerDialog,去除以下代碼:
.
else if (Listener.isEgressBeacon(payload) DataUtils.isBeaconDefined(this.datal) !name.equals(DataUtils.getEgressBeaconListener(this.datal))) {
DialogUtils.showError('You may only define one egress Beacon per team server.\nThere are a few things I need to sort before you can\nput multiple Beacon HTTP/DNS listeners on one server.\nSpin up a new team server and add your listener there.');
}
.

3.去除EICAR后门指纹特征​

試用版有幾個地方存在EICAR特徵字符:X5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*,都需要進行清理:

common.ListenerConfig​

修改pad()函數:
result.append('5O!P%@AP[4\\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*\u0000');
result.append('123\u0000');

resources/template.x64.ps1、resources/template.x86.ps1​

$eicar='X5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*'
$eicar=''

server.ProfileEdits​

c2profile.addCommand('.http-get.server', '!header', 'X-Malware: X5O!P%@AP[4\\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*');
c2profile.addCommand('.http-post.server', '!header', 'X-Malware: X5O!P%@AP[4\\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*');
c2profile.addCommand('.http-stager.server', '!header', 'X-Malware: X5O!P%@AP[4\\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*');
c2profile.addCommand('.stage.transform-x86', 'append', 'X5O!P%@AP[4\\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*');
c2profile.addCommand('.stage.transform-x64', 'append', 'X5O!P%@AP[4\\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*');

common.ArtifactUtils​

因為已經修改了License.isTrial()返回值為false,所以下面這段改不改也沒什麼影響。
if (License.isTrial()) {
packer.addString('X5O!P%@AP[4\\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*');
CommonUtils.print_trial('Added EICAR string to ' + s);
}
添加XOR64.BIN生成payload時,會調用common.ArtifactUtils中的XorEncode()進行編碼:
public static byte[] _XorEncode(final byte[] data, final String arch) {
AssertUtils.TestArch(arch);
if ('x86'.equals(arch)) {
final byte[] decoder=XorStub();
final byte[] payload=XorEncoder.encode(data);
return CommonUtils.join(decoder, payload);
}
if ('x64'.equals(arch)) {
final byte[] decoder=CommonUtils.readResource('resources/xor64.bin');
final byte[] payload=XorEncoder.encode(data);
return CommonUtils.join(decoder, payload);
}
return new byte[0];
}
public static byte[] XorEncode(final byte[] data, final String arch) {
if (License.isTrial()) {
CommonUtils.print_trial('Disabled ' + arch + ' payload stage encoding.');
return data;
}
AssertUtils.Test(data.length 16384, 'XorEncode used on a stager (or some other small thing)');
return _XorEncode(data, arch);
}
試用版不會進行payload stage encoding,所以試用版軟件包中並沒有帶xor.bin/xor64.bin文件,如果有這兩個文件的話,可以添加到resources/xor.bin、resources/xor64.bin路徑下。 Github上有熱心老哥提供了xor64的生成腳本:https://github.com/verctor/CS_xor64
源碼逐個修改完,重新編譯更新到cobaltstrike.jar包中,再拷貝替換掉原版的jar包就OK了。
來源:https://kingx.me/CobaltStrike-Patch...b/KqdEriieNVOkW3wfLlT8KENWSwf6Q0D8e1W2M7rT6wf KJjzY9tGrZayatztD6XzibijhFgIRssm4IOl9C4tXRHlv%2BAnfFkxBZEg0o9Gxtcj%2F3JK%2BBoxbXm13S71rM3rLGZQQQdYwYH1pXd%2BdQqnYdS7ZSJNnGHzQvefkqw6kQ%3D%3D

 
返回
上方