首页
社区
课程
招聘
[原创]SEH和SafeSEH
发表于: 2014-6-21 22:07 21813

[原创]SEH和SafeSEH

2014-6-21 22:07
21813

  昨天写了个驱动,用vs2010编译不了,但是wdk可以编译。vs2010提示是


  查了很多资料也不知道什么原因,有的说打开/Gs选项,然后链接上一个bufferoverflowU.lib文件,但是出错提示更多符号找不到,仔细看了下问题是链接ntoskrnl.lib的时候有个loadcfg.obj找不到__security_cookie的符号,其实这个符号很常见,用于检测堆栈是否被溢出的,/Gs开关就是控制是否做这个检测的。问题是我链接了那个提供这个符号lib还是不行。试了下xp却可以编译。在vs的目录搜索loadcfg,发现了loadcfg.c的文件,看了下里面用到了__security_cookie,用winhex打开ntoskrnl.lib也能搜到loadcfg.obj,所以问题出在这个.c文件,它也参加了编译和链接。用loadcfg.c里面的其他内容搜索到了原因,应该SafeSEH需要关闭,链接命令加上SafeSEH:NO就行了(还不懂求解释)。结合代码和资料复习了一下SEH,并学习了一下SafeSEH。不过后来搜其他结构的时候发现原来早就有这个资料了,但是就当笔记记录一下吧。
  随便写个函数,然后Release编译下
1,SecurityCheck,这是普通的打开/Gs需要进行检查的


  函数会用__security_cookie xor加密一下ebp,存放起来,也会加密一下scopetable的地址。ebp-10就是异常框架的起点了。在函数结尾,会将ebp ^ cookie的值异或上正确的ebp,用_security_check_cookie检查结果和cookie是否相等,不相等说明ebp-1c的位置被修改了,所以能简单地阻止被溢出。溢出我没研究过。。。还有xxxx的位置,是异常分发下来填写的,用GetExceptionInformation获取这个xxxx,xxxx,xxxx+4就是Context和ExceptionRecord的结构指针, r0分发的时候把2个结构打包到用户堆栈。
2,SafeSEH
  异常分发到r3之后的顺序是KiUserExceptionDispatcher -> RtlDispatchException,不考虑VEH的话,会先判断这2个条件:异常处理的框架在堆栈,异常处理的Handler不在堆栈上,不满足就RaiseException。调用ZwQueryInformationProcess查看一下ProcessExecuteFlags属性,得到ExecuteOption。之后就是RtlIsValidHandler,来检测是否Handler是否正常, ExecuteOption作为参数参入RtlIsValidHandler。
  RtlIsValidHandler-> RtlLookupFunctionTable,查看一下信息。

.text:77EE8B68                 mov     esi, _LdrpInvertedFunctionTable ; 这个是需要检查的模块数目。
.text:77EE8B6E                 cmp     esi, ebx
.text:77EE8B70                 jz      loc_77EDD3F6
.text:77EE8B76                 dec     esi
.text:77EE8B77
.text:77EE8B77 loc_77EE8B77:                           ; CODE XREF: RtlLookupFunctionTable(x,x,x)+69 j
.text:77EE8B77                                         ; RtlLookupFunctionTable(x,x,x)+271 j
.text:77EE8B77                 cmp     esi, ebx
.text:77EE8B79                 jl      loc_77EDD3F6    ; 没找到,就跳走,之后会返回0
.text:77EE8B7F                 lea     ecx, [esi+ebx]  ; ebx=0,esi=count-1,这是二分查找,esi是high,ebx是low指针
.text:77EE8B82                 sar     ecx, 1
.text:77EE8B84                 mov     eax, ecx
.text:77EE8B86                 shl     eax, 4          ; 每一项对应的是16byte大小的结构。off0用于解密
.text:77EE8B89                 add     eax, offset unk_77F9AC0C ; 全局变量,是这个模块表的起点
.text:77EE8B8E                 mov     edi, [eax+4]    ; off4是模块映像基地址,off8是大小,offc是SafeSeh的数量
.text:77EE8B91                 mov     edx, [eax+8]
.text:77EE8B94                 add     edx, edi
.text:77EE8B96                 cmp     [ebp+Handler], edi
.text:77EE8B99                 jb      loc_77EE8DA4    ; 调整high的指针
.text:77EE8B9F                 cmp     [ebp+Handler], edx
.text:77EE8BA2                 jb      short loc_77EE8BA9 ; 找到了
.text:77EE8BA4                 lea     ebx, [ecx+1]    ; 调整low指针
.text:77EE8BA7                 jmp     short loc_77EE8B77
.text:77EE8BA9 ; ---------------------------------------------------------------------------
.text:77EE8BA9
.text:77EE8BA9 loc_77EE8BA9:                           ; CODE XREF: RtlLookupFunctionTable(x,x,x)+64 j
.text:77EE8BA9                 mov     ecx, edi
.text:77EE8BAB                 mov     [ebp+var_1C], ecx
.text:77EE8BAE                 mov     ecx, [eax+0Ch]
.text:77EE8BB1                 mov     edx, [ebp+arg_8] ; 第三个参数返回SafeSeh(handler)的个数
.text:77EE8BB4                 mov     [edx], ecx
.text:77EE8BB6                 push    dword ptr [eax] ; off0用于解密
.text:77EE8BB8                 call    _RtlDecodeSystemPointer@4 ; RtlDecodeSystemPointer(x)
.text:77EE8BBD                 mov     esi, eax        ; 得到的结果就是这个模块的SafeSeh表的地址,返回的也是这个值
.text:77EE8ADD                 call    _RtlLookupFunctionTable@12 ; RtlLookupFunctionTable(x,x,x)
.text:77EE8AE2                 xor     edi, edi
.text:77EE8AE4                 mov     [ebp+SafeSehTable], eax
.text:77EE8AE7                 cmp     eax, edi
.text:77EE8AE9                 jz      ModDontHaveSehTable ; 不在模块内部
.text:77EE8AEF                 mov     esi, [ebp+nCount]
.text:77EE8AF2                 cmp     esi, edi
.text:77EE8AF4                 jz      ModDontHaveSehTable ; 或者在模块内部,但是模块本身没有sehtable
.text:77EE8AFA                 cmp     eax, 0FFFFFFFFh
.text:77EE8AFD                 jz      loc_77F4DE4A
.text:77EE8B03
.text:77EE8B03 loc_77EE8B03:                           ; CODE XREF: RtlIsValidHandler(x,x)+65390 j
.text:77EE8B03                 sub     ebx, [ebp+pMouduleBase] ; 得到Handler的Rva
.text:77EE8B06                 xor     edx, edx
.text:77EE8B08                 cmp     esi, edi        ; esi是high索引,edx是low索引
.text:77EE8B0A                 jl      loc_77F37DAE    ; 没有找到
.text:77EE8B10
.text:77EE8B10 loc_77EE8B10:                           ; CODE XREF: RtlIsValidHandler(x,x)+198 j
.text:77EE8B10                 lea     ecx, [edx+esi]
.text:77EE8B13                 sar     ecx, 1
.text:77EE8B15                 mov     edi, [eax+ecx*4] ; SafeSehTable里面的项
.text:77EE8B18                 cmp     ebx, edi
.text:77EE8B1A                 jb      loc_77EE8D94    ; 调整一下索引
.text:77EE8B20                 ja      loc_77EE8C5F    ; 调整一下索引
.text:77EE8B26
.text:77EE8B26 RetTrue:                                ; CODE XREF: RtlIsValidHandler(x,x)+4F5CF j
.text:77EE8B26                                         ; RtlIsValidHandler(x,x)+653C2 j ...
.text:77EE8B26                 mov     al, 1           ; Return True
.text:77EE8B28
.text:77EE8B28 Ret:                                    ; CODE XREF: RtlIsValidHandler(x,x)+65398 j
.text:77EE8B28                                         ; RtlIsValidHandler(x,x)+65403 j
.text:77EE8B28                 mov     ecx, [ebp+var_4]
.text:77EE8B2B                 pop     edi
.text:77EE8B2C                 pop     esi
.text:77EE8B2D                 xor     ecx, ebp
.text:77EE8B2F                 pop     ebx
.text:77EE8B30                 call    @__security_check_cookie@4 ; __security_check_cookie(x)
.text:77EE8B35                 leave
.text:77EE8B36                 retn    8
.text:77F3807A ModDontHaveSehTable:                    ; CODE XREF: RtlIsValidHandler(x,x)+2D j
.text:77F3807A                                         ; RtlIsValidHandler(x,x)+38 j
.text:77F3807A                 cmp     [ebp+ExeOption], edi
.text:77F3807D                 jz      loc_77F37D91
.text:77F38083
.text:77F38083 CmpExecuteOption:                       ; CODE XREF: RtlIsValidHandler(x,x)+4F2E7 j
.text:77F38083                                         ; RtlIsValidHandler(x,x)+653A8 j
.text:77F38083                 mov     eax, [ebp+ExeOption]
.text:77F38086                 and     eax, 30h
.text:77F38089                 cmp     al, 30h         ; ExecuteDispatchEnable  |  ImageDispatchEnable
.text:77F3808B                 jz      RetTrue         ; Return True
.text:77F38091                 jmp     loc_77F4DE69

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

上传的附件:
收藏
免费 3
支持
分享
最新回复 (15)
雪    币: 114
活跃值: (180)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
高大上~
前排支持!
2014-6-22 01:13
0
雪    币: 1556
活跃值: (888)
能力值: ( LV9,RANK:320 )
在线值:
发帖
回帖
粉丝
3
过程挺详细的
2014-6-22 19:42
0
雪    币: 135
活跃值: (63)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
4
感谢ls和lss支持,终于骗到一篇精华。希望今后自己水平能提高。
2014-6-22 20:25
0
雪    币: 26
活跃值: (66)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
文章很不错!!是win7的分析吗?  好像 win8.1判断有所改变了,handle必须是可执行模块的
2014-12-13 11:57
0
雪    币: 1234
活跃值: (302)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
恩,按照lz的意思,我也可以编译通过了。
方法:项目属性->Linker->Command Line->Additional options 加上:/SAFESEH:NO
2015-3-18 11:51
0
雪    币: 2
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
好牛掰!请问楼主是分析的Win7吗?32位64位有影响吗?我想逆一下RtlIsValidHandler。
2015-5-27 13:36
0
雪    币: 135
活跃值: (63)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
8
很久没研究这个了。我记得当时的电脑是Win7 32PAE。Win8和Win7 64都没研究了。
2015-5-27 14:10
0
雪    币: 69
活跃值: (71)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
本人太渣了,无法领会。只能顶顶了。
2015-5-27 15:27
0
雪    币: 2
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
多谢楼主
2015-5-27 16:37
0
雪    币: 2
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
楼主,不好意思再问一下,你的分析工具是IDA吗,请问怎么用IDA分析内核函数?像文章里展示的这样。我会用一点windbg,但是符号帮助太少了。谢谢!
2015-5-27 21:19
0
雪    币: 135
活跃值: (63)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
12
是ida。
2015-5-28 09:01
0
雪    币: 2
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
楼主,实在不好意思,我又来了。。。。琢磨了一天,还是没明白怎么用IDA找到RtlValidHandler的反汇编代码,抓狂中。求楼主指点一下下
2015-5-28 22:24
0
雪    币: 135
活跃值: (63)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
14
ida打开系统dll的时候会提示下载符号表的。你得先配置好_nt_symbol_path,就可以了,搜一下配置,或者把windbg下好的符号表打开一下就可以了。我手机,不好复制粘贴地址。
2015-5-29 00:21
0
雪    币: 2
能力值: (RANK:10 )
在线值:
发帖
回帖
粉丝
15
路过
2017-3-24 09:31
0
雪    币: 1319
活跃值: (1960)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
16
感谢楼主无私分享
2018-7-8 18:22
0
游客
登录 | 注册 方可回帖
返回
//