本文展示了几种动态调用方法,可以利用这些方法绕过Inline和IAT Hook。可以在这里找到概念证明:https://github.com/NVISO-BE/DInvisibleRegistry 。
时至今日,红队的技术已经发生了明显变化,他们越来越多地使用C#编写工具,或者逐步从PowerShell转移到C#。
由于AMSI(反恶意软件扫描接口)、脚本块日志记录等一些变化,利用PowerShell实施的一些攻击活动已经越来越容易被发现和防御。
C#中有一个很好用的功能,就是能够像在C或C++中一样,调用Win32 API并操纵这些低级别的函数。
在C#中利用这些API函数的过程被称为平台调用,简称为P/invoke。微软通过C#中的System.Runtime.InteropServices命名空间来实现这一点。所有这些都由CLR(公共语言运行时)进行管理。下图展示了如何使用P/Invoke来衔接非托管代码和托管代码。
但是,从攻击者视角来说,使用.NET也存在一些缺点。由于CLR负责.NET与机器可读代码之间的转换,因此可执行文件不会直接转换为机器可读的代码。这意味着,可执行文件将其整个代码库存储在程序集中,因此非常容易进行逆向工程。
除了进行逆向以外,我们还越来越多地接触到EDR(终端监测与响应)。借助EDR,组织可以提高其网络安全性,使攻击者变得更加艰难,这显然是一件好事。
即使恶意程序在内存中执行(不接触磁盘,通常也称为“无文件”),由于EDR挂钩了进程,因此也可以捕捉到进程活动,并发现特定函数的执行过程。EDR有能力检查当前正在发生的事情,放行合法的函数调用,并阻止可疑的调用。@CCob发表过一篇关于这个概念,以及如何绕过挂钩的文章。一些EDR可能会挂钩到最底层,即负责Windows内核系统调用的ntdll.dll。下图说明了EDR的工作原理。
EDR如何对ntdll调用进行挂钩以防止恶意软件执行:
EDR主要有两种挂钩方式,分别是IAT Hooking和Inline Hooking(也被称为splicing)。
IAT的全称是导入地址表,我们可以将IAT类比为电话簿,能够在其中查找朋友的号码(所需的函数)。
这个电话簿可能被篡改,EDR可能会更改其中的某个条目,以指向EDR。下面展示了一个图表,说明了IAT Hooking的工作原理。
在这里,我们将EDR视为“恶意代码”:
在示例中,是一个要调用消息框的程序。该程序将在其电话簿中查找消息框的号码(地址),以便进行调用。
程序很难知道有人替换了电话号码(地址),所以每次当它以为在调用消息框时,实际上都在调用EDR。
EDR会接受呼叫(调用),收听消息(调用的函数),如果EDR判断该内容时合法的,则会将消息框的真实地址返回给程序,以便进行实际的调用。
而Inline Hooking的原理可以类比成入侵者把枪顶在了我们要呼叫的朋友的脑袋上。
在Inline Hooking的情况下