• SEH, SAFESEH相关


    SEH, SAFESEH相关

    1,触发seh异常
    让目标程序Read/Write无效地址,如果和栈底相邻的内存只读,尝试覆盖超出栈底

    2,如何找到(显示)要覆盖的SEH
    od语法:dd fs:[0]
    softice语法: dd fs:0

    3,覆盖SEH时需要填充的跳转地址
    需要找一个可以跳转成功的
    pop ?
    pop ?
    retn 
    的代码地址。
    od语法:Ctrl+B/L 5? 5? c3
    softice语法:s -a addr -L length 5? 5? c3
    其中"5?"代表"58-5F"之间的任意值

    4,ntdll!KiUserExceptionDispatcher()流程
    VEH <-- winxp才有

    SEH <-- win2000从这里开始

    UEF 当程序被调试时,UnhandledExceptionFilter() SetUnhandledExceptionFilter()

    5,ntdll!KiUserExceptionDispatcher()检查SEH handler过程
    1) 检查handler是否在线程TEB指定的Stack范围内(fs:[4]~fs:[8]),如果在其中,拒绝执行.
    2) 检查handler是否在已加载模块列表(exe和dll), 如果handler不在这些模块地址范围内,执行.
    3) 如果handler在模块地址范围内,开始检查已注册异常处理程序列表.
    检查过程:
    --------------
    a) if((DLLCharacteristics&0xFF00) == 0x0400), 拒绝执行(No SEH);否则,继续检查.
    b) Load Configuration Directory地址为0(即不存在Load Configuration Directory结构,说明编译时没有设置/safeseh选项),停止检查,执行.
    Load Configuration Directory结构存在,继续检查:
    +00h directory_size // 目录长度介于[0,0x48),停止检查,执行.
    ...
    +40h handlers[] // SEH handler数组指针(元素是SEH handler RVA地址),if(handlers[]==0),停止检查,执行.
    +44h handler_num // SEH handler数组元素个数,if(handler_num==0),停止检查,执行.

    c) 然后开始逐个匹配,发现匹配,调用;没有发现匹配,拒绝调用.

    6,关于DataDirectory[IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG]
    这个是在winnt.h中的定义
    typedef struct {
    DWORD Size;
    DWORD TimeDateStamp;
    WORD MajorVersion;
    WORD MinorVersion;
    DWORD GlobalFlagsClear;
    DWORD GlobalFlagsSet;
    DWORD CriticalSectionDefaultTimeout;
    DWORD DeCommitFreeBlockThreshold;
    DWORD DeCommitTotalFreeThreshold;
    DWORD LockPrefixTable; // VA
    DWORD MaximumAllocationSize;
    DWORD VirtualMemoryThreshold;
    DWORD ProcessHeapFlags;
    DWORD ProcessAffinityMask;
    WORD CSDVersion;
    WORD Reserved1;
    DWORD EditList; // VA
    DWORD SecurityCookie; // VA
    DWORD SEHandlerTable; // VA
    DWORD SEHandlerCount;
    } IMAGE_LOAD_CONFIG_DIRECTORY32, *PIMAGE_LOAD_CONFIG_DIRECTORY32;
    SEHandlerTable 是指向一个Seh处理函数Rva的表格。SEHandlerCount是这个表格的长度。如果这个表格存在,那么只有该表格中的Seh处理函数才是合法的处理函数。如果异常发生时,顺序查找并执行Fs:[0]中的处理函数时,如果认为当前函数非法,则Seh无法继续执行,程序会中止。而且连 UnhandledExceptionFilter都无法执行到。除非PE在被调试,依靠调试器来恢复。
    每个PE有一个单独表格。如kernel32.dll和user32.dll有各自的表格。当PE被载入时,PE的基址,大小、 SEHandlerTable(表格的地址)、SEHandlerCount(长度)会被存在一个表格中。当一个异常发生时,系统每个PE的基址和大小检查当前seh处理函数属于哪一个PE,然后取出相应的表格地址和长度。由于是载入时就已经取出,载入后SEHandlerTable和 SEHandlerCount就没什么用处了,对它进行修改当然也没什么用了。但修改表格内容还是有效的。
    如果seh处于动态申请的内存中,因为不处于任何一个PE Image内,所以seh是没有任何限制的,否则如果不在相应表格中,会导致PE中止。visual c++的try..catch等的seh处理函数会自动加入该表格。但如果使用inline asm对fs:[0]进行操作加seh是无效的,如果发生异常只会导致PE中止。
    目前基本所有的壳软件都是将loadconfig删除,对该PE基本没什么影响。但如果要保留的话,则需要将Pe Image内的seh处理函数加入到该表格中。微软称这个表格中的处理函数为"safe handler",
    关掉safe handler的开关在Liker|CommandLine 加入/SAFESEH:NO
    尝试动态修改内存中的SEHandlerTable,except_handler顺利得到控制权.

    7,针对Win2003/WinXP SP2对SEH handler(异常处理函数)地址的突破方法
    1) 不在stack里面, 在heap里.
    对IE等浏览器,用js等heapspray分配堆,用堆内地址覆盖SEH handler.

    2) 在已加载模块的范围外.
    用代码页的跳转地址,比如0x7FFA1571(win2000/xp/2003 chs通用地址)

    3) 在系统dll里面,且是该dll注册过的异常处理函数.
    利用已注册的SEH handler,利用性不大.

    8,OD的safeseh插件OllySSEH
    用其分析已加载模块,查看哪些DLL是/SafeSEH OFF:
    /Safeseh ON 只能选已注册的SEH handler地址来跳.
    /Safeseh OFF 可以选里面的地址(pop/pop/ret地址)来跳.
    No SEH (DLLCharacteristics&0xFF00) == 0x0400, 不能跳.
    下载地址:
    http://www.openrce.org/downloads/details/244/OllySSEH

  • 相关阅读:
    快速整理sql表结构到wiki
    mac subline批量处理行
    iphone7忘记手机屏幕密码
    docker 常用命令
    初窥响应式布局
    用jquery写的一个图片轮播插件
    javascript中的对象和创建对象的主要模式
    用户注册界面(带js特效)
    用javascript实现简易留言板
    用javascript实现的购物车实例
  • 原文地址:https://www.cnblogs.com/huhu0013/p/3875312.html
Copyright © 2020-2023  润新知