尝试修复cobaltstrike xor64.bin
未完成
- 作者:c4bbage
- 时间:2017.9.14
- 链接:http://dobest1.com/cobaltstrike-xor
概述
在cobaltstrike3.8中在资源里我们缺少xor64.bin文件,早期流传3.x中存在xor.bin不知道来自哪里(我看了下所有3.x中没有xor.bin,而且3.x的xor.bin和2.5的xor.bin并不一样),但是这并不影响我们使用cobaltstrike。 没有xor64.bin永远美中不足。
调用位置
所有代码是以3.8为例
// common.ArtifactUtils
public static byte[] XorEncode(byte[] data, 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)");
AssertUtils.TestArch(arch);
if ("x86".equals(arch))
{
byte[] decoder = CommonUtils.pickOption("resources/xor.bin");
byte[] payload = XorEncoder.encode(data);
return CommonUtils.join(decoder, payload);
}
if ("x64".equals(arch))
{
byte[] decoder = CommonUtils.readResource("resources/xor64.bin");
byte[] payload = XorEncoder.encode(data);
return CommonUtils.join(decoder, payload);
}
return new byte[0];
}
在x86架构中采用的是pickOption读取xor.bin,以下是调用过程及部分主要函数。
// common.CommonUtils
public static byte[] pickOption(String file)
{
List options = readOptions(file);
byte[] result = (byte[])options.get(rand(options.size()));
return result;
}
// readOptions方法
public static List readOptions(String file)
{
LinkedList results = new LinkedList();
try
{
byte[] data = readResource(file);
DataInputStream in = new DataInputStream(new ByteArrayInputStream(data));
while (in.available() > 0)
{
// 读取四个字节,并返回一个int值。文件指针后移
int len = in.readInt();
// available 判断读写操作前先得知数据流里有多少个字节可以读取
if (len > in.available())
{
print_error("readOptions: " + file + " has bad length: " + len + " > " + in.available());
return results;
}
byte[] next = new byte[len];
// read()方法最多
in.read(next);
results.add(next);
}
}
catch (IOException ioex)
{
MudgeSanity.logException("readOptions: " + file, ioex, false);
}
return results;
}
// common.CommonUtils
public static byte[] readResource(String f)
{
try
{
InputStream in = resource(f);
if (in != null)
{
byte[] result = readAll(in);
in.close();
return result;
}
print_error("Could not find resource: " + f);
}
catch (IOException ioex)
{
MudgeSanity.logException("readResource: " + f, ioex, false);
}
return new byte[0];
}
public static InputStream resource(String f)
throws IOException
{
if (new File(f).exists()) {
return new FileInputStream(new File(f));
}
return CommonUtils.class.getClassLoader().getResourceAsStream(f);
}
想法
整个流程只是简单的读取文件编码文件,流程简析如下:
- CommonUtils.pickOption("resources/xor.bin")
- CommonUtils.readOptions()
- CommonUtils.readResource()
X64 省略了前面操作 - CommonUtils.resource()
我对上面的代码做了摘取,进行了调试 readResource()的结果和pickOption的结果一样。 xor.bin x86 的数据结构是
struct xorbin{
int length;
unsigned char shellcode[];
};
/** xir.bin 3.8 HEX数据
0x00, 0x00, 0x00, 0x38, 0xFC, 0xE8, 0x00, 0x00, 0x00, 0x00, 0xEB, 0x2B, 0x5D, 0x8B, 0x45, 0x00, 0x83, 0xC5, 0x04, 0x8B, 0x4D, 0x00, 0x31, 0xC1, 0x83, 0xC5, 0x04, 0x55, 0x8B, 0x55, 0x00, 0x31, 0xC2, 0x89, 0x55, 0x00, 0x31, 0xD0, 0x83, 0xC5, 0x04, 0x83, 0xE9, 0x04, 0x31, 0xD2, 0x39, 0xD1, 0x74, 0x02, 0xEB, 0xE8, 0x58, 0xFF, 0xE0, 0xE8, 0xD0, 0xFF, 0xFF, 0xFF,
//
0x00, 0x00, 0x00, 0x38 => 56
*/
在x64 xor64.bin没有length这一位(四字节),只有shellcode部分。 想起以前都是用一个xor.bin,到这里了我们是不是可以干了
0xFC, 0xE8, 0x00, 0x00, 0x00, 0x00, 0xEB, 0x2B, 0x5D, 0x8B, 0x45, 0x00, 0x83, 0xC5, 0x04, 0x8B, 0x4D, 0x00, 0x31, 0xC1, 0x83, 0xC5, 0x04, 0x55, 0x8B, 0x55, 0x00, 0x31, 0xC2, 0x89, 0x55, 0x00, 0x31, 0xD0, 0x83, 0xC5, 0x04, 0x83, 0xE9, 0x04, 0x31, 0xD2, 0x39, 0xD1, 0x74, 0x02, 0xEB, 0xE8, 0x58, 0xFF, 0xE0, 0xE8, 0xD0, 0xFF, 0xFF, 0xFF,
用C32修改xor.bin数据 把xor64.bin添加到jar中,生成64位的windows Executable,后来发现CS逻辑代码上,走不到到XorEncoder.encode(),X64系统中,也是走的x86体系的payload作为data数据,比如vncdll.x64.dll。 就先到这里,下次分析下2.5版本的xor.bin.