2013-04-13 82 views
0

我通過使用此代碼中的程序集在c文件中創建自我異常處理程序: 使用程序集c中的異常自我處理程序

__asm 
    { 
     pushad 
     mov esi, offset Handler 
     push esi 
     push dword ptr fs:[0] 
     mov dword ptr fs:[0], esp 
     push u32Param 
     call pFunc; 
     jmp NoException 

Handler: 

     mov esp, [esp + 8] 
     pop dword ptr fs:[0] 
     add esp, 4 
     popad 
     mov eax, 0x80000000  
     jmp ExceptionHandled 

NoException: 

     pop dword ptr fs:[0] 
     add esp, 40 

ExceptionHandled: 
    } 

This code is simple exception handling in assembly.
This code works in new created vc project.
But in my project it make an exception and vc says that there is an invalid exception handler.

Any Suggestion?

+1

嘗試獲得除了簡單的拆卸離子處理程序由vC++編譯,以查看注入哪些入口/出口代碼塊。 (相當於g中的-S - objdump -d file.o也會這樣)。在例程本身中也可能沒有特殊的入口/出口代碼,但是您需要將入口點作爲信號處理程序插入到例程中。 –

+0

我已經看到由vc生成的生成的程序集,但問題不在於程序集源,它不適用於我的大項目是控制檯應用程序,當我創建一個新項目(不管Win32/Console)時,它的工作原理! –

回答

2

If you are following this article , which it seems you are, then why aren't you properly restoring the stack as shown in the code there?

The code in the article:

18 NoException&;Handler:    ;;No Exception Occured 
19  pop dword ptr fs:[0]   ;;Restore Old Exception Handler 
20  add esp, 32 + 4     ;;ESP value before SEH was set. 32 for pushad and ... 
21 ExceptionHandled&;Handler:   ;;...4 for push offset Handler. (No Restore State) 
22          ;;Exception has been handled, or no exception occured 

Your code:

NoException: 

     pop dword ptr fs:[0] 
     add esp, 8 

ExceptionHandled: 

32 in that code is to undo pushad,4將撤消push esi。你爲什麼有8個? 32 + 4≠8

如果這就是你想從堆棧中刪除u32Param(如果pFunc你不這樣做),那麼你應該去做這兩條線之間:

call pFunc; 
    add esp, 4 
    jmp NoException 

我的版本:

// file: tst.c 
// compile with Open Watcom C/C++ 1.9: wcl386.exe /q /we /wx tst.c 
// ditto with debug info: wcl386.exe /q /we /wx /d2 tst.c 
#include <stdio.h> 

unsigned __stdcall func(volatile unsigned* p) 
{ 
    return *p; 
} 

unsigned blah(unsigned (__stdcall *pFunc)(volatile unsigned*), volatile unsigned* u32Param) 
{ 
    unsigned result = 0; 

    __asm 
    { 
     pushad 
//  mov esi, offset Handler // Open Watcom C/C++ says Handler is undefined 
//  push esi 

//  lea eax, blah 
//  add eax, Handler - blah // this difference doesn't come out correct with Open Watcom C/C++ 
//  add eax, 78 // 78 is Handler - blah // this is unreliable 
//  push eax 

     push 0xFDCB4321 
     jmp GetHandlerAddr 
    GotHandlerAddr: 
     pop eax 
     add esp, 4 
     push eax 

     push dword ptr fs:[0] 
     mov dword ptr fs:[0], esp 
     push u32Param 
     call dword ptr [pFunc] 

     jmp NoException 

    GetHandlerAddr: 
     call Handler // this will place &Handler on the stack 
    Handler: 
     cmp dword ptr [esp + 4], 0xFDCB4321 
     je GotHandlerAddr 

     mov esp, [esp + 8] 
     pop dword ptr fs:[0] 
     add esp, 4 
     popad 
     mov eax, 0x80000000  
     jmp ExceptionHandled 

    NoException: 

     pop dword ptr fs:[0] 
     add esp, 32 + 4 

    ExceptionHandled: 

     mov result, eax 
    } 

    return result; 
} 

int main(void) 
{ 
    volatile unsigned n = 0x113355AA; 
    printf("%08X\n", func(&n)); 
    printf("%08X\n", blah(&func, &n)); 
    printf("%08X\n", blah(&func, (volatile unsigned*)0)); 
    printf("%08X\n", blah(&func, (volatile unsigned*)0)); 
    return 0; 
} 

輸出:

113355AA 
113355AA 
80000000 
80000000 
+0

你是對的,我用這篇文章,並改變它從輸入使用的函數,我想運行safe.And也是正確的糾正堆棧,我已經刪除了普沙和popa,但返回它的測試獲得正確運行的機會。不幸的是,這個問題不在堆棧上,當發生異常時,vc調試器會顯示「找到無效的異常處理程序」。它永遠不會跳到處理程序,所以堆棧不重要,直到這樣的跳轉。 –

+0

如果您的程序不在調試器下運行,該怎麼辦?我在這裏沒有問題(使用Open Watcom C/C++)。 –

+0

它會崩潰。我很困惑!這種方法是自我處理程序最流行的方式,我在很多惡意軟件程序集上看到了大量的時間。但我找不到有什麼問題。 –