内存中的猎者

【技术分享】内存中的猎者

2017-06-30 14:23:53 阅读:969次 点赞(0) 收藏 来源: endgame.com
image
作者:Kp_sover

t015801781875774b4c.png

图1.1

译者:Kp_sover

预估稿费:200RMB

投稿方式:发送邮件至linwei#360.cn,或登陆网页版在线投稿

前言


在大量复杂数据中筛选可能存在的威胁并且在软件生命周期中任何一个阶段定位出恶意行为真的是一项艰巨任务,想要做到这些,安全研究员必须不断学习新的攻击技术和检测方法的专业知识。

内存驻留类型的恶意软件顾名思义会将它自己存放在内存中,这个技术已经出现超过十年,而且有越演欲烈的趋势,这可能归功于内存技术的普及和代码数量的增加,但另一方面,这也恰巧反映了它在逃逸安全软件和管理员检测方面的优势,这个曾经只在顶尖攻击者中出现的技术,现在基本已经被滥用了,我将和我的团队通过研究最常见的内存攻击技术,希望能开发出一种可扩展的、低误杀率的检测方法。

攻击技术相关


当然,如果能理解 shellcode注入,反射型DLL注入,内存模块,进程和模块HOLLOWING,GARGOYLE(ROP/APCs注入)等方面的知识,这对于理解内存检测技术会很有用处!

0x1、SHELLCODE 注入


最常见的内存驻留技术就是shellcode注入,它可以归纳为下面四个步骤:

1、OpenProcess 打开目标进程,获得句柄。

2、VirtualAllocEx 在目标进程里分配一块内存。

3、WriteProcessMemory 向刚分配的区域写入我们的shellcode。

4、CreateRemoteThread 远程创建一个新的线程去执行我们的shellcode。

著名的 Poison Ivy 远控 就是使用了这个技术,这大概也是很多APT组织喜欢上它的主要原因吧! 

如果你用 x64dbg 打开 Poison Ivy 植入端程序并在VirtualAllocEx处设置断点,很快你就会看到它分配内存的情景及后续相关操作.

t0108a707ec88cf3521.png

图1.2

t011b7fa81936ef7ef7.png

图1.3

在图1.2中,push 40 表示将 VirtualAllocEx  函数分配的内存页设置为 PAGE_EXECUTE_READWRITE,也就是可读写可执行属性,下面这张图片是用

 ProcessHacker 获取到的 Poison Ivy 的内存分配图,你可以看到大量具有 RWX 属性的区段.

t0171a0f8190e14901f.png

图1.4

通常情况下,代码段的类型是 ‘image’,并且会被关联到磁盘文件,但这里却是 ‘Private’ 属性并且没有被关联到磁盘文件,它们就是没有关联的可执行区段或者被称为 浮动的代码,从这些内存区域启动的线程通常都是不正常的,这也可以作为鉴定恶意代码的一个重要因素,通过 ProcessHacker 我们还可以看到它的调用堆栈,在这里我们可以清晰地看到 红色箭头处的 几个内存地址没有和任何模块关联.

t01b7c5ad306d23f564.png

图1.5

0x2、反射型DLL注入


另一种内存攻击技术是由  Steven Fewer 发现,被称为反射型DLL注入,Metasploit’s 的 Meterperter 第一次将这种技术应用于实战,现在仍然有很多恶意软件使用这种技术,反射型DLL注入取代了需要 Windows加载器执行的方式,通过将自身dll文件映射到内存中获得执行,它注入进程的方式和 shellcode 注入相同,唯一不同的就是这里shellcode被换成了实现自我映射的loader.它负责将读取到的dll 通过解析输入表、修复重定向、最后调用 DllMain的方式让其获得执行,攻击者可以用高级语言例如c/c++来利用这个技术,而不再需要苦逼的汇编语言了。

典型的反射型DLL注入例如 Meterpreter所采用的,是很容易被检测到的,因为它在进程里留下了大量的 RWX 内存区段,即使 Meterpreter已经断开连接, 这些没有关联的可执行内存区段的开始位置是完整的 MZ/PE头,就像下面看到的一样!但需要注意的是这些残留的数据是可以被抹除的.

t01e319236f41bf6e37.png

图1.6

t01ea7f93774a201786.png

图1.7

当然,在dll里面也可以很方便的实现一个导出函数,例如 ReflectiveLoader(),这个函数没有任何参数,返回值就是dllmain的地址,通常用来定位dllmain!

t011cd729342d3269a1.png

图1.8

0x3、内存模块


内存模块注入是另外一种内存驻留技术,它和反射型dll注入相似,但不同的是 前者由注射器或加载器负责将dll映射到内存 变成了 自己映射到内存,相当于它自身实现了 LoadLibrary 的功能,而且它不再需要释放文件到磁盘上,最开始的植入器只能映射到当前进程,但现在已经可以将其映射到远程进程中去,为了躲避检测,现在大多数的植入器都没有改动dll的区段属性,并且不再设置其为RWX.

NetTraveler 就是采用这一技术的恶意软件,NetTraveler运行后,会解压核心功能函数并将它映射到内存中去,区段属性也被设置成像一个正常的dll一样,但只是这些似乎还是不够,因为它的内存区段中仍然具有 ‘Private’ 这个特征.

t01242690b3aa13e90d.png

图1.9

它的活动线程 是从这几个 private 区域启动,ProcessHacker 的 堆栈回溯里也仍然能看到下面几个恶意的区域.

t01874f1ba4c0504212.png

图1.10

Winnti  是另一个采用这种内存模块注入技术的恶意软件,相比之下,它的特征更明显些,因为它的内存区段属性有一个仍为 RWX.

t0136e92986868025ca.png

图1.11

但 Winnti 有一个值得肯定的地方就是它的 MZ/PE头已经被擦除了,这也让它更难被检测到!

t0127bcf15d6a123c8e.png

图1.12

0x4、进程 Hollowing


进程 Hollowing 是逃避安全软件和安全员检测的另一个攻击技术,它通过创建一个 挂起(CreateProcess 的 Creation 标志设置为CREATE_SUSPENDED) 的进程,删除(Hollowing)进程空间原本的内容,然后重新分配并写入新的payload进去,用SetThreadContext重定向原来的执行流程到新的payload处,最后调用ResumeThread让进程恢复运行。

现在这类技术大多的变种都会用 Create/Map 相关的API替代 敏感的 WriteProcessMemory ,并且修改入口点跳转来代替 敏感的 SetThreadContext 函数.

DarkComet 是很多使用这种技术的恶意软件中的一个!这里有几个常规的方法可以检测进程Hollowing,其中一个是检测进程是否被以  CREATE_SUSPENDED  方式创建,就像DarkComet 样本展示的这样.

t01f058044236a12352.png

图1.13

0x5、模块覆盖


本文到目前为止,讨论的所有技术都会导致存在 无镜像关联的 执行代码,因此这些也都非常容易得被检测到,但模块覆盖技术却并不会这样,这让的它更难被检测,这个技术具体实现是将 目标进程中没有使用的模块映射到进程中,之后再将自己的payload写在映射的模块里,Flame 是第一个被大众所知的使用这个技术的恶意软件,不久, Careto 和 Odinaff也被发现使用这个技术。当然也有很多其他检测技术可以感知到 模块覆盖 这种技术,比如将内存中的数据和磁盘上相应的模块文件关联起来作对比!

0x6、GARGOYLE


GARGOYLE 已经被证明是一种可以逃避大多数安全软件检测的内存驻留技术,它利用当前线程被唤醒时APC中的注册函数会被执行的机制,当线程被唤醒时会首先执行APC队列中的被注册的函数,当payload执行完成后再往后执行.检测这种攻击技术的方法是通过检查线程和用户APC调用来发现隐藏其中的恶意 ROP 链.

检测内存攻击


鉴于这些技术已经被扩散和极其容易获取的特性,安全相关人员必须对基于内存的攻击技术保持警惕,并主动在网络中搜寻它们的踪迹,然而,现实是大多是安全产品不具备大规模检测这种内存攻击技术的能力,并且离检测这类攻击在技术上还差的太多. 正是因为这样,Endgame 团队才在这上面做了很多有意义的探索,并且希望能将这种针对以上所有攻击并实现低误报检测的方法引入我们现有的安全产品中.

鉴于这种针对内存驻留检测技术的差距所涉及到的用户规模和带来的影响,提高所有相关环节而并不止是客户的能力迫在眉睫,因此,我们和 Jared Atkinson 在他所开发的 powershell tool 工具 Get-InjectedThreads 上进行了合作, 这个工具提供了在检测内存驻留技术上相对低误报的方式,它的大概原理就是 通过扫描系统上所有活跃线程的可疑启动地址,安全员通过它去检测自己所在的网络的话,可以很快的鉴别出大多数类型的内存驻留线程.

这个脚本通过 NtQueryInformationThread 函数查询每个活跃线程的启动地址,然后

用 VirtualQueryEx  去查询启动地址相关的区段属性,如果这个线程的启动地址是没有关联并且可执行的(不是 image 属性),那么我们基本可以考虑它是一个注入线程,下面这张图展示了在检测 9002 RAT sample 时的情景.

t01df75a6d306ca0cbc.png

图1.14

这个脚本可以捕获大多数恶意软件家族所使用的shellcode注入技术、反射型注入技术、内存模块注入技术以及 进程hollowing注入 技术,但是需要指出的是,它并不能完全替代安全产品在综合阻止内存注入方面的能力,比如 Endgame.

企业如何大范围检测内存驻留


EndGame 企业安全产品 能够检测上面所述的所有驻留技术(或许更多),提供了市场上能找到的最好的来定位内存中威胁的功能。我们不仅仅依赖于简单的检测方法,例如监控众所周知的调用系统API实现注入的流程,而且具备有效地分析内存并找到所有已知的恶意软件驻留的能力。为我们的用户提供了基于线程级的关于注入代码的可见性,以及复杂的后续操作,例如检查到注入的代码后仅仅只会挂起恶意注入的线程来修复威胁。我们的产品在阻止注入过程中和注入成功后的情景都很有效,而且速度快的不行,在几秒钟之内即可定位几万个主机的威胁.

和任何无签名文件的检测技术一样,误报率是我们很看重的一方面,我们从研究到开始应用这个技术去阻止内存驻留的每一步,如何降低误报率都是我们最看重的地方!

大多数误报都和安全软件,即时(JIT)编译代码或DRM保护/打包应用程序这三方面有关。

0xa、很多安全产品有时会为系统中的某些或所有进程注入代码,以增强其行为检测能力。但这样做的缺点是如果安全产品都滥用这种方法的话,它最终可能会损害到系统的安全性,并使得真正的内存驻留恶意软件更难被检测.

0xb、即时(JIT)编译代码是另一个容易导致误报的情况,它会实时生成 存在于没有任何关联或者浮动内存中的代码,.NET或Java应用程序是使用JIT技术最典型的例子,不过幸运的是,JIT 类型的检测比流氓安全产品的行为更容易识别和过滤.

0xc、最后,应该牢记使用数字版权管理(DRM)方案打包或保护的应用程序。同时这些应用程序可能会在内存中才解密或者使用混淆技术去阻止被调试或者逆向破解,同样恶意软件也会使用相同的技术来避开安全软件的检测并阻止安全从业者的分析。

但经过精细的设计和额外的测试,我们的安全产品现在达到了一个很低的误报率,我相信它会使得我们 EndGame 的用户很快摆脱内存驻留软件的危害.

结论


我们的对手当然会不断地开发新的技术去躲避检测并达到他们的目的,内存驻留技术也不例外,过去十多年,在这一领域我们一直处于十分被动的地位.幸运的是,通过掌握最新的技术,我们慢慢板回了一局。EndGame 就是通过开发出检测这种攻击的方法,从而在无文件攻击检测这一领域获得了市场领导者的地位(加入了我们另一个关键的技术  other key technologies),想要了解更多内存攻击检测方面的知识,查看我们在SANS威胁寻找和IR峰会上演示的幻灯片


本文由 安全客 翻译,转载请注明“转自安全客”,并附上链接。
原文链接:https://www.endgame.com/blog/technical-blog/hunting-memory


为您推荐了相关的技术文章:

  1. ne2der
  2. 会找漏洞的时光机: Pinpointing Vulnerabilities
  3. 八月 | 2016 | jinzihao's homepage
  4. 蝴蝶效应与程序错误 —— 一个渣洞的利用
  5. Windows 10下MS16-098 RGNOBJ整数溢出漏洞分析及利用

原文链接: bobao.360.cn