首页
社区
课程
招聘
在异常处理函数中同步线程的问题————一段代码
发表于: 2011-9-1 20:06 6719

在异常处理函数中同步线程的问题————一段代码

2011-9-1 20:06
6719

#include<stdio.h>
#define _WIN32_WINNT 0x0500

#include<windows.h>
#include<tchar.h>
#include<Tlhelp32.h>
HANDLE      hevent,hevent2;

/*
ZwMapViewOfSection
76E44ED0 Z>  B8 A8000000              MOV EAX,0A8
76E44ED5     BA 0003FE7F              MOV EDX,7FFE0300
76E44EDA     FF12                     CALL DWORD PTR DS:[EDX]
76E44EDC     C2 2800                  RETN 28
*/
//注意---硬编码!
PVOID       addr = 0x76E44EDC;//ZwMapViewOfSection 中retn 28的地址

DWORD   myThread( PVOID context )
{
    while( 1 ){
        WaitForSingleObjectEx( hevent,INFINITE,TRUE );
        printf("ok\n");
        MessageBox(NULL,_T("thread exit!"),_T("text"),MB_OK );
    }

}
int main()
{  
    HMODULE     hMod;
    HANDLE      hThread;
    DWORD       oldpt;

    hevent = CreateEvent( NULL,FALSE,FALSE,NULL );
    hevent2 = CreateEvent( NULL,FALSE,FALSE,NULL );
    hThread = CreateThread( NULL,0,(LPTHREAD_START_ROUTINE)myThread,0,0,NULL);
    MessageBox( NULL,_T("1"),_T("OK"),MB_OK );

    //在ZwMapViewOfSection的retn 28地址处写入int 3断点
    VirtualProtect( addr,1,PAGE_EXECUTE_READWRITE,&oldpt );
    *(PBYTE)addr = 0xcc;
    getch();

    __try{
    LoadLibrary(_T("123.dll"));     //触发断点异常,任意加载一个dll即可
    }
    __except(
        *(PBYTE)addr = 0xc2,                //恢复原始代码
        SetEvent( hevent ),                 //设置myThread中等待的事件
        WaitForSingleObject( hevent2,INFINITE),//使当前线程处于等待状态
    EXCEPTION_CONTINUE_EXECUTION ){;}
    getch();
    return 0;
}
/*
myThread中的WaitForSingleObject不返回,不知为何?

我做了些实验,好像那个断点位置有些特殊。具体什么原因导致出现上述情况就不明白了。
还有,要是去掉异常处理中那条等待语句,使异常线程恢复运行的话,一切工作正常。
*/


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

收藏
免费 6
支持
分享
最新回复 (8)
雪    币: 113
活跃值: (100)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
2
楼主的意思大概是,LoadLibrary会调用 ZwMapViewOfSection,于是在这个函数的结尾处插入一个断点,SEH中捕获断点的时候,作些处理。

好像你的那个代码有点问题。应该是
WaitForSingleObject( hThread,INFINITE),
而不是
WaitForSingleObject( hevent2,INFINITE),
吧。你没有地方设置hevent2。

你说断点位置比较特殊,不知道特殊在哪,还有,你的线程好像也没做什么事,为什么要创建呢?
2011-9-1 22:05
0
雪    币: 1689
活跃值: (379)
能力值: ( LV15,RANK:440 )
在线值:
发帖
回帖
粉丝
3
这里我故意没有设置hevent2,目的是让发生异常的线程停在那里。然后设置其它线程等待的事件,让其它线程进行处理。可是,那个myThread没有进行调度,不知为何。
2011-9-1 22:22
0
雪    币: 1689
活跃值: (379)
能力值: ( LV15,RANK:440 )
在线值:
发帖
回帖
粉丝
4
为什么没人帮忙呢?自己再顶一次吧。
2011-9-2 19:53
0
雪    币: 39
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
也许你的hEvent的值在代码执行过程中被改变了也不一定了,你可以调试看看。

MSDN上对WaitForSignleObject的描述
Remarks
The WaitForSingleObject function checks the current state of the specified object. If the object's state is nonsignaled, the calling thread enters the wait state. It uses no processor time while waiting for the object state to become signaled or the time-out interval to elapse.

The function modifies the state of some types of synchronization objects. Modification occurs only for the object whose signaled state caused the function to return. For example, the count of a semaphore object is decreased by one.
2011-9-2 22:07
0
雪    币: 1689
活跃值: (379)
能力值: ( LV15,RANK:440 )
在线值:
发帖
回帖
粉丝
6
我感觉不是这个原因,上边msdn的这个描述我是看过的。hevent是事件内核对象句柄,调试过程显示它的值并没有发生变化。只要异常处理一结束。那个线程就可以结束等待状态,这个事实说明我们设置的确实是hevent事件。
2011-9-2 22:51
0
雪    币: 185
活跃值: (86)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
7
给你改了改:
1, 选择ZwMapViewOfSection不合适, LdrLoadDll开始就有SEH, 你的__except block得不到执行,被内部的
    SEH filter给吃掉了。
2, 处理int3的重新执行要调节EIP。

#include "stdafx.h"
#include<stdio.h>
#include <conio.h>
#include<windows.h>
#include<tchar.h>

HANDLE hevent,hevent2;
HMODULE DllHandle;
PUCHAR Address;

DWORD myThread( PVOID context )
{
    WaitForSingleObjectEx(hevent,INFINITE,TRUE);
    printf("myThread is signaled! \n");

        printf("singal main thread to run ... \n");
        SetEvent(hevent2);
        return 0;
}

LONG WINAPI ExceptionFilter(
        __in struct _EXCEPTION_POINTERS* ExceptionInfo
        )
{
        //
        // don't care about other exception conditions.
        //

        printf("Enter ExceptionFilter \n");

        if (*Address == (UCHAR)0x8b) {
                return EXCEPTION_CONTINUE_SEARCH;
        }

        if (*Address != (UCHAR)0xcc) {
                return EXCEPTION_CONTINUE_SEARCH;
        }

        //
        // recover old opcode
        //

    *Address = 0x8b,              

        //
        // adjust EIP to old value to re-execute
        //

        ExceptionInfo->ContextRecord->Eip = (DWORD)(Address - 1);

    SetEvent(hevent);
    WaitForSingleObject(hevent2, INFINITE);

        printf("Exit ExceptionFilter \n");
        return EXCEPTION_CONTINUE_EXECUTION;
}

int main(int argc, TCHAR *argv)
{  
    HANDLE  hThread;
        ULONG OldProtect;

    hevent = CreateEvent( NULL,FALSE,FALSE,NULL );
    hevent2 = CreateEvent( NULL,FALSE,FALSE,NULL );
    hThread = CreateThread( NULL,0,(LPTHREAD_START_ROUTINE)myThread,0,0,NULL);

        DllHandle = LoadLibrary(_T("kernel32.dll"));
        Address = (PUCHAR)GetProcAddress(DllHandle, "LoadLibraryW");
        printf("LoadLibrary address: 0x%08x \n", Address);

    VirtualProtect(Address, 1, PAGE_EXECUTE_READWRITE, &OldProtect);
    *(PUCHAR)Address = (UCHAR)0xcc;

    putch(getch());
        printf("\n");

    __try{
            DllHandle = LoadLibrary(_T("mshtml.dll"));
                printf("LoadLibrary is called : 0x%08x \n", DllHandle);
    }
        __except(ExceptionFilter(GetExceptionInformation())) {
        }
   
        getch();
    return 0;
}
2011-9-3 19:43
0
雪    币: 1689
活跃值: (379)
能力值: ( LV15,RANK:440 )
在线值:
发帖
回帖
粉丝
8
看了看你的分析,不过还是有些问题。
1,一般而言,更低层的异常处理器如果不能处理异常,其会返回EXCEPTION_CONTINUE_SEARCH,使高层的异常处理器得到处理机会,我的那个问题就是这样的。我在我的异常处理器中放了个Beep函数,结果有声音产生。说明我们得到了异常处理控制,而不是你所说的被吃掉了。
2,系统在一轮分发异常给调试器时,对于陷阱类异常,结构中的ExceptionAddress和对应线程上下文中eip的值是不同的,eip = ExceptionAddress + 1.不过,系统在将异常控制传给我们的异常处理代码之前把这个调整了,eip = ExceptionAddress。我们无需自己将eip值减1.(当时我也郁闷这个问题,看有人写调试循环,明明自己设了cc,eip确不调整,直接continue execution了)

不过还是谢谢你的热心人帮助。麻烦了。还得继续寻找原因……
2011-9-3 21:45
0
雪    币: 1689
活跃值: (379)
能力值: ( LV15,RANK:440 )
在线值:
发帖
回帖
粉丝
9
求高人指教!!!!
2011-10-22 18:26
0
游客
登录 | 注册 方可回帖
返回
//