首页
论坛
课程
招聘
[系统底层] 《Windows 10 Control Flow Guard Internals》 Reading Notes
2021-4-30 17:24 2668

[系统底层] 《Windows 10 Control Flow Guard Internals》 Reading Notes

erfze 活跃值
10
2021-4-30 17:24
2668

0x00 前言

Wikipedia:

Control Flow Guard (CFG) was first released for Windows 8.1 Update 3 (KB3000850) in November 2014. Developers can add CFG to their programs by adding the /guard:cf linker flag before program linking in Visual Studio 2015 or newer.

As of Windows 10 Creators Update (Windows 10 version 1703), the Windows kernel is compiled with CFG.The Windows kernel uses Hyper-V to prevent malicious kernel code from overwriting the CFG bitmap.

CFG operates by creating a per-process bitmap, where a set bit indicates that the address is a valid destination. Before performing each indirect function call, the application checks if the destination address is in the bitmap. If the destination address is not in the bitmap, the program terminates.This makes it more difficult for an attacker to exploit a use-after-free by replacing an object's contents and then using an indirect function call to execute a payload.

 

Windows CFG是Control-Flow Integrity(CFI)的具体实现,该机制由Windows 8.1 Update 3 (KB3000850)开始引入,需编译器和操作系统相结合,目的在于防止不可靠间接调用。漏洞利用常常通过修改间接调用地址以劫持执行流,而CFG会于编译链接期间将程序所有间接调用地址记录在PE文件中,并在执行所有间接调用前增加校验,若间接调用地址被修改,则抛出异常。


 

环境:

  • 物理机OS:Windows 10 20H2 x64
  • 物理机WinDbg:10.0.17134.1
  • 虚拟机OS:Windows 10 1511(10586.164) x86
  • 虚拟机WinDbg:10.0.19041.685
  • VMware:VMware Workstation 15 Pro
  • Visual Studio 2019

0x01 How CFG Works:User Mode Part

使用如下代码进行编译及调试:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
typedef int(*fun_t)(int);
 
int foo(int a)
{
    printf("hellow world %d\n",a);
    return a;
}
class CTargetObject
{
public:
    fun_t fun;
};
int main()
{
    int i = 0;
    CTargetObject *o_array = new CTargetObject[5];
    for (i = 0; i < 5 ; i++)
        o_array[i].fun = foo;
    o_array[0].fun(1); 
    return 0;
}

启用CFG:

 

 

修改"调试信息格式":

 

 

编译完成,dumpbin.exe /headers /loadconfig Project1.exe

 

 

可以看到CFG已启用。

 

  • Guard CF address of check-function pointer:指向___guard_check_icall_fptr,载入PE后,其指向ntdll!LdrpValidateUserCallTarget

  • Guard CF address of dispatch-function pointer:Reserved
  • Guard CF function table:指向RVA列表,供NT内核使用

  • Guard CF function count:RVA数量
  • Guard Flags

 

系统若不支持CFG,则不对___guard_check_icall_fptr进行更新(如下为Windows 7 SP1 x86):

 

 

若系统支持CFG,首先是nt!PspPrepareSystemDllInitBlock(由nt!NtCreateUserProcess—>nt!PspAllocateProcess—>nt!PspSetupUserProcessAddressSpace调用)初始化ntdll!LdrSystemDllInitBlock

 

 

其偏移0x60为Bitmap Address,0x68为Bitmap Size。

 

 

载入PE文件时,ntdll!LdrpCfgProcessLoadConfig会校验OptionalHeader.DllCharacteristics

 

 

修改_guard_check_icall_nop指向ntdll!LdrpValidateUserCallTarget

 

 

间接调用地址传递给ECX寄存器:

 

 

下面来看ntdll!LdrpValidateUserCallTarget校验过程:

 

  1. 获取ntdll!LdrSystemDllInitBlock+0x60处Bitmap Address,当前进程空间每8 Bytes对应Bitmap中1 bit[mov edx, ds:dword_6A30C1A0]
  2. 获取指向Destination Address低8位(即1 Byte)范围内的Bitmap值(低8位范围:0x00—0xFF,256 Bytes;Bitmap值:32 bit—328=256 Bytes)[mov eax, ecx;shr eax, 8;`mov edx, [edx+eax4]`]
  3. Destination Address是否以0x10对齐,是则取最低字节前5位作为索引获取bit;否则取最低字节前5位再与0x01作或运算之后作为索引获取bit

  1. 该bit值为1,则Destination Address合法

注:

 

shr eax, 3 即Destination Address/8,Bitmap中每1bit对应进程空间8 Bytes。bt指令功能如下:

 

 

由于SRC寄存器是32位,故POSITION值需模32(0x20—0010 0000),如此一来,便做到取Destination Address最低字节前5位为索引。若Destination Address合法,则直接retn,非法会交由ntdll!RtlpHandleInvalidUserCallTarget,最终触发int 29中断。

 

在执行mov edx,dword ptr [edx+eax*4]时,若EAX寄存器已被篡改,则可能会触发内存访问异常,而ntdll!LdrpValidateUserCallTarget中并未加入异常处理,其异常处理位于ntdll!RtlDispatchException中:

 

 

 

 

最后交由ntdll!RtlpHandleInvalidUserCallTarget来处理:

 

0x02 How CFG Works:Kernel Mode Part

nt!MiInitializeCfg首先调用nt!PsIsSystemWideMitigationOptionSet校验注册表HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Kernel\MitigationOptions键值:

 

 

nt!PsIsSystemWideMitigationOptionSet函数返回零,则调用MmCreateSection

 

 

Section Object Address保存于nt!MiState+0x604处,InputMaximumSize为0x3000000。

 

nt!MiCfgInitializeProcess会调用nt!MiReferenceCfgVad向0xC0802174处写入_MI_CFG_BITMAP_INFO

 

 

0x03 参阅链接


[看雪官方培训] Unicorn Trace还原Ollvm算法!《安卓高级研修班》2021年6月班火热招生!!

收藏
点赞4
打赏
分享
最新回复 (2)
雪    币: 159
活跃值: 活跃值 (657)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
fengyunabc 活跃值 1 2021-4-30 19:11
2
0
感谢分享!
雪    币: 7030
活跃值: 活跃值 (5720)
能力值: ( LV12,RANK:210 )
在线值:
发帖
回帖
粉丝
pureGavin 活跃值 2 2021-4-30 22:59
3
0
感谢分享
游客
登录 | 注册 方可回帖
返回