前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >[ Windows 10 x64中的RFG(Return Flow Guard)技术研究 ]1

[ Windows 10 x64中的RFG(Return Flow Guard)技术研究 ]1

作者头像
franket
发布2022-06-29 16:44:59
4310
发布2022-06-29 16:44:59
举报
文章被收录于专栏:技术杂记
代码语言:javascript
复制
让我们梳理下一RFG防护的基本思路:
1) 在每一个函数开始处,”读”取当前栈rsp里面的值到rax中,该值就是函数的返回地址,我们记作return_value
2) 然后将rax里面值”写”入fs:[rsp] 偏移处 , 也就是保留函数返回地址return__value的值到”影子栈“Thread Control stack当中。
3) 在函数即将结束的时候检测当前返回地址值return_value和fs:[rsp]中保存的是否一致,如果一致,函数正常返回,如果不一致将跳向 
xxx!_guard_ss_verfiy_failure_rdx, 表明可能受到攻击者利用,进而会引发int29异常,进程崩溃,阻止漏洞利用的进行。

那么有哪些机制决定RFG开启功能呢?
1 内核里面的全局变量nt!MnEnableRfg用来决定系统是否开启支持RFG功能
2 针对具体进程的PE头部,PE.LoadConfigDirectory.GuardFlag标记用来决定该进程是否支持RFG功能
3 可以通过SetProcessMitigationPolicy来动态设定一个进程是否开启RFG功能。

关于RFG涉及到的很多细节大家可以参考腾讯玄武实验室的一篇blog:
http://xlab.tencent.com/cn/2016/11/02/return-flow-guard/

[0x02] 防护层面分析:

现在我们需要回答3个问题以及为什么这样会起到很强的保护作用。
1  fs可否被攻击者控制进而改写?
2  fs对应的影子栈指向何处?
3  如何保证fs指向的“影子栈”位置是随机的,可以不被攻击者预测到?

下面我将从用户层和内核层面来分析这个3个问题。

[0x02.1] 用户层面的分析
首先,在用户层面fs值本身是不可被改写(换句话说,特殊的方式下需要可利用的漏洞具有相当的便利性才有可能,存在fs被清空为0的可能,此时2个栈重合,防御失效),也就不存攻击者可以通过修改fs寄存器的值来
伪造出“影子栈”的内容,绕过上面提到的步骤3的验证。

因为用户层面,fs选择子的值不具有意义,例如下面的fs寄存器的值,见下面代码


0:018> r
rax=00007ffd5bb757b5 rbx=0000023b69a2cea0 rcx=0000023b69a2cea0
rdx=00007ffd5c09dff8 rsi=0000007311dfb730 rdi=0000023b69a2cea0
rip=00007ffd5bb3d250 rsp=0000007311dfb588 rbp=0000023b6a736050
 r8=0000007311dfb600  r9=0000023b5092ce50 r10=00000fffab76eaf2
r11=0000007311dfb5c8 r12=fffc000000000000 r13=0000000000000124
r14=0000023b50943040 r15=0000023b6a736050
iopl=0         nv up ei pl nz na po nc
cs=0033  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000206
chakra!Js::ExternalObject::IsObjectAlive+0x4:
00007ffd`5bb3d250 6448890424      mov     qword ptr fs:[rsp],rax fs:00000073`11dfb588=00007ffd5bb757b5
                                   

 这里的fs=53 不具有操作上的含义,53是选择子,你可以任意修改它为其它任何值,不影响程序的运行(在x86下是不可以被修改的)。同样我们
 也不能在调试器通过dg命令表来获得fs真正含义。 

0:018> dg fs
                                                    P Si Gr Pr Lo
Sel        Base              Limit          Type    l ze an es ng Flags
---- ----------------- ----------------- ---------- - -- -- -- -- --------
0053 00000000`10181000 00000000`00000fff Data RW Ac 3 Bg By P  Nl 000004f3

也就是说上面的00000000`10181000并不是fs所指向的真正的基地址,在我调试的环境下总是指向一个未被映射的地址空间。 

0:018> !address 00000000`10181000
Usage:                  Free
Base Address:           00000000`00000000
End Address:            00000000`7ffe0000
Region Size:            00000000`7ffe0000 (   2.000 GB)
State:                  00010000          MEM_FREE
Protect:                00000001          PAGE_NOACCESS
Type:                   <info not present at the target>

本文系转载,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文系转载前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档