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】Eclipse常用快捷键
Eclipse常用快捷键 * 1.补全代码的声明:alt + / * 2.快速修复: ctrl + 1 * 3.批量导包:ctrl + shift + o * 4.使用单行注释:ctrl + / * ...
- word缺失字体问题
问题 有时候word会确实一些公文使用的字体,所以会用微软雅黑进行自动替换.所以你看到和打印的仿宋等字体,会被替换成微软雅黑,这对于政府公文或者企业行政文档是不好的. 这里面的字体替换你可以用一些字体 ...
- 深度解读SSH免密登录
深度解读SSH免密登录 我们都知道SSH是LINUX下很常用的命令,用来远程登陆其他的LINUX系统.如果只有一台,那也只是一个密码 ,也到还好.但如果是一个集群,每次都输入密码登录,难免会拉低效率. ...
- 基础概念(3):怎么写一个c程序?
总结卡片: 遵循c语言的规则,即可写出c程序.规则下有两个重要概念:函数与变量.就好像游戏中的打仗,要考虑怎么打,谁来打."怎么打"就是流程,把流程封装起来就是函数,流程也叫算法. ...
- django_url配置
前言 我们在浏览器访问一个网页是通过url地址去访问的,django管理url配置是在urls.py文件.当一个页面数据很多时候,通过会有翻页的情况,那么页数是不固定的,如:page=1.也就是url ...
- Natasha 4.0 探索之路系列(四) 模板 API
Natasha 模板 Natasha 在编译单元的基础上进行了封装整理, 并提供了多种模板帮助开发者构建功能. 使用此篇的 API 前提是您对 C# 非常熟悉, 对系统的一些类型足够了解. 据此 Na ...
- Servlet-HttpServletResponse类介绍及作用和两个响应流介绍
Servlet-HttpServletResponse类 HttpServletResponse类和HttpServletRequest类一样.每次请求进来,Tomcat服务器都会创建一个Respon ...
- 集合框架-HashSet存储自定义对象
1 package cn.itcast.p4.hashset.test; 2 3 import java.util.HashSet; 4 import java.util.Iterator; 5 6 ...
- 浅谈kali : arpspoof工具原理
Arpspoof工具 介绍 arpspoof是一个通过ARP协议伪造数据包实现中间人攻击的kali工具. 中间人攻击虽然古老,但仍处于受到黑客攻击的危险中,可能会严重导致危害服务器和用户.仍然有很多变 ...
- 『无为则无心』Python基础 — 42、Python中文件的读写操作(二)
目录 (5)文件对象方法(重点) 1)写方法 2)读方法 3)seek()方法 4)tell()方法 (6)关闭 (7)综合练习:读取大文件 (5)文件对象方法(重点) 1)写方法 @1.语法 对象对 ...