TP最近全体升级成了ACE系列的驱动保护,强度弱了亿点。
发现了它有个很有意思的功能,启动程序大约几分钟后,就不能再修改其代码段的内存属性,也就不能修改其只读代码段了。效果跟BE使用的remap非常相似。
那么它到底是remap还是if hook还是什么别的其他技术来实现的呢。
首先它的内存属性前后都是image类型的没变过,不太像remap。关闭系统的ifhook后,仍然不能修改。说明ACE是通过其他方式来实现的。
先调用ZwProtectVirtualMemory来修改目标代码段的属性看下错误,
C000009D是个很少见的错误,一般来说跟内存相关的API不会返回这样的错误值。
看一下ntos中都有什么地方会返回这个错误
可以看到,还是非常少的,寥寥无几,我们一个一个尝试,把这里的错误值改成其他的错误,最终我们得到了ZwProtectVirtualMemory的错误是由VslpEnterIumSecureMode引起的。
可是修改内存属性为什么会进入这个函数里面呢。查看一下调用栈
原来在MmProtectVirtualMemory中,如果被修改的内存vad flag中如果第16位是1,则会进入这个分支。
+0x000 VadType : Pos 0, 3 Bits
+0x000 Protection : Pos 3, 5 Bits
+0x000 PreferredNode : Pos 8, 6 Bits
+0x000 PrivateMemory : Pos 14, 1 Bit
+0x000 PrivateFixup : Pos 15, 1 Bit
+0x000 Enclave : Pos 16, 1 Bit
+0x000 PageSize64K : Pos 17, 1 Bit
+0x000 RfgControlStack : Pos 18, 1 Bit
+0x000 Spare : Pos 19, 8 Bits
+0x000 NoChange : Pos 27, 1 Bit
+0x000 ManySubsections : Pos 28, 1 Bit
+0x000 DeleteInProgress : Pos 29, 1 Bit
+0x000 LockContended : Pos 30, 1 Bit
+0x000 Lock : Pos 31, 1 Bit
第16是一个叫Enclave的位,那么这个位是做什么用的。在intel-sgx-enclave-support-in-windows-10-fall-update-threshold-2.pdf这个文档中,
可以看到
这些是WIN10中新加入的对INTEL SGX(software guard extensions)的支持。SGX只有Skylake后的CPU才支持
而且SGX的可信内存所在VAD的Enclave位才会被赋值,且不能被修改内存属性。
那么TP是用SGX API来实现的吗?
可惜并没有发现TP调用MiCreateEnclave和MiInitializeEnclave等相关SGX有关的API。我们看下后面不能修改内存属性后的进程VAD情况
!vad 0000000140000000 1
nt!_MMVAD
+0x000 Core : _MMVAD_SHORT
+0x040 u2 : <unnamed-tag>
+0x048 Subsection : 0xffffa58f`36e4a090 _SUBSECTION
+0x050 FirstPrototypePte : 0xffffd184`0733f000 _MMPTE
+0x058 LastContiguousPte : 0xffffd184`073aa818 _MMPTE
+0x060 ViewLinks : _LIST_ENTRY [ 0xffffa58f`36e4a018 - 0xffffa58f`36e4a018 ]
+0x070 VadsProcess : 0xffffa58f`5885d081 _EPROCESS
+0x078 u4 : <unnamed-tag>
+0x080 FileObject : (null)
0: kd> dx -id 0,0,ffffa58f5885d080 -r1 (*((ntkrnlmp!_MMVAD_SHORT *)0xffffa58f36e13ce0))
(*((ntkrnlmp!_MMVAD_SHORT *)0xffffa58f36e13ce0)) [Type: _MMVAD_SHORT]
[+0x000] NextVad : 0xffffa58f5602e370 [Type: _MMVAD_SHORT *]
[+0x008] ExtraCreateInfo : 0xffffa58f57e036b0 [Type: void *]
[+0x000] VadNode [Type: _RTL_BALANCED_NODE]
[+0x018] StartingVpn : 0x140000 [Type: unsigned long]
[+0x01c] EndingVpn : 0x14d703 [Type: unsigned long]
[+0x020] StartingVpnHigh : 0x0 [Type: unsigned char]
[+0x021] EndingVpnHigh : 0x0 [Type: unsigned char]
[+0x022] CommitChargeHigh : 0x0 [Type: unsigned char]
[+0x023] SpareNT64VadUChar : 0x0 [Type: unsigned char]
[+0x024] ReferenceCount : 0 [Type: long]
[+0x028] PushLock [Type: _EX_PUSH_LOCK]
[+0x030] u [Type: <unnamed-tag>]
[+0x034] u1 [Type: <unnamed-tag>]
[+0x038] EventList : 0x0 [Type: _MI_VAD_EVENT_BLOCK *]
0: kd> dx -id 0,0,ffffa58f5885d080 -r1 (*((ntkrnlmp!_MMVAD_SHORT *)0xffffa58f36e13ce0)).u
(*((ntkrnlmp!_MMVAD_SHORT *)0xffffa58f36e13ce0)).u [Type: <unnamed-tag>]
[+0x000] LongFlags : 0x1003a [Type: unsigned long]
[+0x000] VadFlags [Type: _MMVAD_FLAGS]
[+0x000] VolatileVadLong : 0x1003a [Type: unsigned long]
0: kd> dx -id 0,0,ffffa58f5885d080 -r1 (*((ntkrnlmp!_MMVAD_FLAGS *)0xffffa58f36e13d10))
(*((ntkrnlmp!_MMVAD_FLAGS *)0xffffa58f36e13d10)) [Type: _MMVAD_FLAGS]
[+0x000 ( 2: 0)] VadType : 0x2 [Type: unsigned long]
[+0x000 ( 7: 3)] Protection : 0x7 [Type: unsigned long]
[+0x000 (13: 8)] PreferredNode : 0x0 [Type: unsigned long]
[+0x000 (14:14)] PrivateMemory : 0x0 [Type: unsigned long]
[+0x000 (15:15)] PrivateFixup : 0x0 [Type: unsigned long]
[+0x000 (16:16)] Enclave : 0x1 [Type: unsigned long]
[+0x000 (17:17)] PageSize64K : 0x0 [Type: unsigned long]
[+0x000 (18:18)] RfgControlStack : 0x0 [Type: unsigned long]
[+0x000 (26:19)] Spare : 0x0 [Type: unsigned long]
[+0x000 (27:27)] NoChange : 0x0 [Type: unsigned long]
[+0x000 (28:28)] ManySubsections : 0x0 [Type: unsigned long]
[+0x000 (29:29)] DeleteInProgress : 0x0 [Type: unsigned long]
[+0x000 (30:30)] LockContended : 0x0 [Type: unsigned long]
[+0x000 (31:31)] Lock : 0x0 [Type: unsigned long]
可以看到VAD FLAG中的Enclave确实被赋值了,我们对这里下一个写入断点。断到了ACE-BASE中,ACE其实只是把这个标志位手动置上去了。
ACE内存保护原理:
bool ProtectMemory(void* memory)
{
auto vad = GetMemoryVad(memory);
if(vad) {
vad->Core.u.LongFlags &= 0x10000;
}
}
[培训]二进制漏洞攻防(第3期);满10人开班;模糊测试与工具使用二次开发;网络协议漏洞挖掘;Linux内核漏洞挖掘与利用;AOSP漏洞挖掘与利用;代码审计。