首页
社区
课程
招聘
[求助]邪门儿了!在学习异常处理时的出现的问题
发表于: 2008-2-20 11:44 7145

[求助]邪门儿了!在学习异常处理时的出现的问题

2008-2-20 11:44
7145

这个问题都困饶我好几天~

看了
SEH in ASM 研究(一)by hume   
Structured Exception Handling

帖子后自己写了一个线程异常处理的程序,就成功了一次,其他的时候再也不成功了,甚至把上面文章里的例子直接搬下来用都不成功.出现的问题是:总是不调用我自己的异常处理程序,OB里显示"调试的程序无法处理异常".不知道看帖子的朋友有没有出现这样问题 help me !


[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 7
支持
分享
最新回复 (15)
雪    币: 846
活跃值: (221)
能力值: (RANK:570 )
在线值:
发帖
回帖
粉丝
2
不要用OD,或者出异常的时候按SHIFT + F9才会进入你的异常流程
直接F9相当于调试器接管了异常,这样你的异常程序就得不到执行权了
2008-2-20 13:15
0
雪    币: 207
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
我就是 SHIFT + F9 运行的

而且我直接运行程序 那程序直接就退出了 (我的调试函数里 还有个MessageBox呢,也不出来)
2008-2-20 14:40
0
雪    币: 485
活跃值: (12)
能力值: ( LV9,RANK:490 )
在线值:
发帖
回帖
粉丝
4
把代码拿出来让版主看看吧
2008-2-20 15:24
0
雪    币: 207
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
代码   

Structured Exception Handling文章里的代码我直接拿来都出现这个问题

// bbs.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"

DWORD  scratch;

EXCEPTION_DISPOSITION
__cdecl
_except_handler(
    struct _EXCEPTION_RECORD *ExceptionRecord,
    void * EstablisherFrame,
    struct _CONTEXT *ContextRecord,
    void * DispatcherContext )
{
    unsigned i;

    // Indicate that we made it to our exception handler
    printf( "Hello from an exception handler\n" );

    // Change EAX in the context record so that it points to someplace
    // where we can successfully write
    ContextRecord->Eax = (DWORD)&scratch;

    // Tell the OS to restart the faulting instruction
    return ExceptionContinueExecution;
}

int main()
{
    DWORD handler = (DWORD)_except_handler;

    __asm
    {                           // Build EXCEPTION_REGISTRATION record:
        push    handler         // Address of handler function
        push    FS:[0]          // Address of previous handler
        mov     FS:[0],ESP      // Install new EXECEPTION_REGISTRATION
    }

    __asm
    {
        mov     eax,0           // Zero out EAX
        mov     [eax], 1        // Write to EAX to deliberately cause a fault
    }

    printf( "After writing!\n" );

    __asm
    {                           // Remove our EXECEPTION_REGISTRATION record
        mov     eax,[ESP]       // Get pointer to previous record
        mov     FS:[0], EAX     // Install previous record
        add     esp, 8          // Clean our EXECEPTION_REGISTRATION off stack
    }

    return 0;
}



就是不调用"_except_handler"

我用的VC8.0 是不是编译器设置了什么东东 ?

以前我也发过帖子 问这个问题 一直没解决
上传的附件:
2008-2-20 15:46
0
雪    币: 207
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
实在是自己找不出问题所在了 才发上来的
2008-2-20 15:48
0
雪    币: 485
活跃值: (12)
能力值: ( LV9,RANK:490 )
在线值:
发帖
回帖
粉丝
7
我基本上看不懂C++,有可能的话把你编译的程序也拿出来吧。
2008-2-20 15:55
0
雪    币: 207
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
谢谢你 看看这个程序在你的 机子上运行正常不?

bbs.rar
上传的附件:
2008-2-20 16:41
0
雪    币: 485
活跃值: (12)
能力值: ( LV9,RANK:490 )
在线值:
发帖
回帖
粉丝
9

运行不了,OD也无法调试,帮不上忙了。
上传的附件:
2008-2-20 16:58
0
雪    币: 207
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
to :

petnt

我换成静态编译!

重新发上来

bbs.rar
上传的附件:
2008-2-20 18:27
0
雪    币: 207
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
刚自己用OB跟到了这点

7C92EB0A   > \5B            pop     ebx
7C92EB0B   .  59            pop     ecx                              ;  0012F99C
7C92EB0C   .  6A 00         push    0
7C92EB0E   .  51            push    ecx
7C92EB0F   .  53            push    ebx
7C92EB10   .  E8 3DF7FFFF   call    ZwRaiseException

call    ZwRaiseException 后到下面这点

7C92E252 >/$  B8 B5000000   mov     eax, 0B5
7C92E257  |.  BA 0003FE7F   mov     edx, 7FFE0300
7C92E25C  |.  FF12          call    dword ptr [edx]
7C92E25E  \.  C2 0C00       retn    0C

7FFE0300 是0 直接回到 程序原来出错的地方 OD提示"调试的程序无法处理异常"
2008-2-20 18:44
0
雪    币: 846
活跃值: (221)
能力值: (RANK:570 )
在线值:
发帖
回帖
粉丝
12
我一开始也遇到麻烦了,说说解决的过程,你以后自己尝试解决吧,否则你学逆向就跟没学一样~~

在程序代码产生异常之后进入系统异常处理函数

7C92EAF0    8B1C24          mov     ebx, dword ptr [esp]
7C92EAF3    51              push    ecx
7C92EAF4    53              push    ebx
7C92EAF5    E8 C78C0200     call    7C9577C1
7C92EAFA    0AC0            or      al, al
7C92EAFC    74 0C           je      short 7C92EB0A
7C92EAFE    5B              pop     ebx
7C92EAFF    59              pop     ecx
7C92EB00    6A 00           push    0
7C92EB02    51              push    ecx
7C92EB03    E8 11EBFFFF     call    ZwContinue
7C92EB08    EB 0B           jmp     short 7C92EB15
7C92EB0A    5B              pop     ebx
7C92EB0B    59              pop     ecx
7C92EB0C    6A 00           push    0
7C92EB0E    51              push    ecx
7C92EB0F    53              push    ebx
7C92EB10    E8 3DF7FFFF     call    ZwRaiseException

这段代码中ZwContinue是恢复环境,返回原来的程序执行流程的,即正常情况下,如果SEH可以顺利解决问题,这里便是系统异常处理的终点了

注意到在它前面的这两行指令
call    7C9577C1
or      al, al
je      short 7C92EB0A

对于只简单返回成功或者失败的函数(即返回值类型为BOOL的),1为成功,而0为失败。先在这里下断点,可以看到它的返回失败。也就是说这个函数出错了。然后可以跟踪进里面看看了~~以同样的方法观察每一个CALL的返回值,哪个CALL失败了,在那个CALL下断点再来~~~直到最后看到下面代码引起我的注意

7C9579C8    8BFF            mov     edi, edi
7C9579CA    55              push    ebp
7C9579CB    8BEC            mov     ebp, esp
7C9579CD    51              push    ecx
7C9579CE    FF75 08         push    dword ptr [ebp+8]
7C9579D1    E8 738EFDFF     call    RtlImageNtHeader
7C9579D6    F640 5F 04      test    byte ptr [eax+5F], 4
7C9579DA    0F85 CF7C0100   jnz     7C96F6AF
7C9579E0    8D45 FC         lea     eax, dword ptr [ebp-4]
7C9579E3    50              push    eax
7C9579E4    6A 0A           push    0A
7C9579E6    6A 01           push    1
7C9579E8    FF75 08         push    dword ptr [ebp+8]
7C9579EB    E8 668EFDFF     call    RtlImageDirectoryEntryToData
7C9579F0    85C0            test    eax, eax
7C9579F2    0F84 D8010000   je      7C957BD0
7C9579F8    8B4D FC         mov     ecx, dword ptr [ebp-4]

RtlImageNtHeader和RtlImageDirectoryEntryToData都是PE结构相关的函数。我对PE结构不太熟悉,所以觉得SEH跟PE有关联觉得有点奇怪,于是就打开baidu搜索“seh pe结构”。然后是我找到的相关解释:

关于DataDirectory[IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG]的一些介绍
关于LoadConfig的介绍较少,这里简单介绍一下
这个是在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

摘自:http://www.crack520.cn/bencandy.php?fid-9-id-362-page-1.htm(鉴于挂马网站太多,我用百度快照看的,如果你直接点链接中毒了,后果自负)

我动态修改内存中的SEHandlerTable,except_handler顺利得到控制权。补充一句,这个东西LORDPE、PETOOL、PEID三个工具都没有标出相应的成员,很恶心
2008-2-20 19:07
0
雪    币: 207
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13


看了后

知道了 还要自动校检一下 异常处理
2008-2-20 19:35
0
雪    币: 485
活跃值: (12)
能力值: ( LV9,RANK:490 )
在线值:
发帖
回帖
粉丝
14
谢谢版主,学到了知识
2008-2-20 19:41
0
雪    币: 136
活跃值: (105)
能力值: ( LV9,RANK:140 )
在线值:
发帖
回帖
粉丝
15
感谢  看来还是自己动手好

不懂VC
2008-2-20 20:47
0
雪    币: 207
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
16
恩自己修改了一下 成功了

自己还发现了 VC8.0 以前的 版本编译出来的程序的这个目录
<IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG (10) 载入配置目录>  
里面都是0

所以这些文章里面的例子都能用呢
SEH in ASM 研究(一)by hume   

哈哈 好高兴 谢谢非常感谢斑斑
2008-2-20 20:59
0
游客
登录 | 注册 方可回帖
返回
//