SEH + ThreadContext

Discussion in 'WASM.WIN32' started by Twister, Sep 19, 2007.

  1. Twister

    Twister New Member

    Blog Posts:
    0
    Доброго времени суток.

    Устанавливаю SEH-обработчик потоку. В нем хочу просто посмотреть состояние регистров на момент возникновения ошибки.
    Но вместо валидной инфы вижу порнуху (в обоих случаях получения контекста - см. код). Подскажите, где ошибся (хотя есть подозрения, что дело, все-таки, в гребаной самостоятельности Делфей):
    Code (Text):
    1. function _handler(Exception: PExceptionRecord; EstablisherFrame: DWORD; Context: PContext; DispContext: DWORD): DWORD; cdecl;
    2. var
    3.   c: _CONTEXT;
    4. begin
    5. ShowMessage('EDI: ' + IntToHex(Context.Edi, 8) + #13#10 +
    6.             'ESI: ' + IntToHex(Context.Esi, 8) + #13#10 +
    7.             'EBX: ' + IntToHex(Context.Ebx, 8) + #13#10 +
    8.             'EDX: ' + IntToHex(Context.Edx, 8) + #13#10 +
    9.             'ECX: ' + IntToHex(Context.Ecx, 8) + #13#10 +
    10.             'EAX: ' + IntToHex(Context.Eax, 8) + #13#10 );
    11. c.ContextFlags := CONTEXT_FULL;
    12. GetThreadContext(hThread, c);
    13. ShowMessage('GetThreadContext' + #13#10 + 'EDI: ' + IntToHex(C.Edi, 8) + #13#10 +
    14.             'ESI: ' + IntToHex(C.Esi, 8) + #13#10 +
    15.             'EBX: ' + IntToHex(C.Ebx, 8) + #13#10 +
    16.             'EDX: ' + IntToHex(C.Edx, 8) + #13#10 +
    17.             'ECX: ' + IntToHex(C.Ecx, 8) + #13#10 +
    18.             'EAX: ' + IntToHex(C.Eax, 8) + #13#10 );
    19. end;
    20.  
    21. procedure ThreadProc(lpParam: pointer); stdcall;
    22. asm
    23.   //int   3
    24.   push  offset _handler
    25.   xor   eax, eax
    26.   push  fs:[eax]
    27.   mov   fs:[eax], esp
    28.   mov   ebx, $12345678
    29.   mov   [eax], eax
    30. end;
    31.  
    32. procedure TForm1.Button3Click(Sender: TObject);
    33. var
    34.   ThId: DWORD;
    35. begin
    36. hThread := CreateThread(nil, 0, @ThreadProc, nil, 0, ThId);
    37. end;
    Так же, попутно, хочу задать еще два вопроса:
    1. Какое значение будет содержать _EXCEPTION_RECORD.ExceptionCode в случае трассировочного исключения?
    2. Какое значение следует вернуть функции _handler, чтоб выполнение кода продолжилось со следующей инструкции, после вызвавшей исключение. Интересует как числовое значение, так и сишный хидер с соответствующей константой (а то Сей у меня на данный момент нет)?

    Заранее спасибо.
     
  2. Asterix

    Asterix New Member

    Blog Posts:
    0
    Code (Text):
    1. {$O+}
    2. function _except_handler(
    3.     ExceptionRecord:PExceptionRecord;
    4.     EstablisherFrame:Pointer;
    5.     ContextRecord:PContext;
    6.     DispatcherContext:Pointer): EXCEPTION_DISPOSITION; cdecl;
    7. begin
    8.   ContextRecord.Eip := __seh.SafeEip;
    9.   ContextRecord.Esp := __seh.PrevEsp;
    10.   ContextRecord.Ebp := __seh.PrevEbp;
    11.   // Tell the OS to restart the faulting instruction
    12.   Result := ExceptionContinueExecution;
    13. end;
    14.  
    15.  
    16. {$O-}
     
  3. asmfan

    asmfan New Member

    Blog Posts:
    0
    1.
    Code (Text):
    1. STATUS_BREAKPOINT     equ 80000003h
    2. STATUS_SINGLE_STEP    equ 80000004h
    У меня вылезало первое, но не исключаю и второе.
    2.
    тут было полнейшее враньё :)
    Не обязательно иметь - качай у хатча windows.inc много полезной информации в одном месте.
    А вопче на форуме и сайте уже куча раз поднималась тема обработки исключений... и причём, оооочень детально, с широкими исследованиями в области.
     
  4. wasm_test

    wasm_test wasm test user

    Blog Posts:
    0
    передается же параметр Context:PCONTEXT, который как раз представляет из себя указатель на контекст. зачем делать GetThreadContext/SetThreadCOntext я не знаю
     
  5. rain

    rain New Member

    Blog Posts:
    0
    просто хотел уточнить, прочитаны ли соответствующие статьи на сайте?
     
  6. asmfan

    asmfan New Member

    Blog Posts:
    0
    Тааак... терь я чой-то гоню
    Code (Text):
    1. FORMAT  PE GUI 4.0
    2.  
    3. INCLUDE 'win32wxp.inc'
    4. ENTRY   start
    5.  
    6.  
    7. ;EXCEPTION_EXECUTE_HANDLER = 1
    8. ;EXCEPTION_CONTINUE_SEARCH = 0
    9. ;EXCEPTION_CONTINUE_EXECUTION = -1
    10.  
    11. ; For SEH Kernel
    12. ExceptionContinueExecution = 0
    13. ExceptionContinueSearch = 1
    14. ExceptionNestedException = 2
    15. ExceptionCollidedUnwind = 3
    16.  
    17. EXCEPTION_MAXIMUM_PARAMETERS = 15
    18. SIZE_OF_80387_REGISTERS = 80
    19. MAXIMUM_SUPPORTED_EXTENSION = 512
    20.  
    21. struct  EXCEPTION_POINTERS
    22.   pExceptionRecord  dd      ?
    23.   ContextRecord     dd      ?
    24. ends
    25.  
    26. struct  EXCEPTION_RECORD
    27.   ExceptionCode         dd      ?
    28.   ExceptionFlags        dd      ?
    29.   pExceptionRecord      dd      ?
    30.   ExceptionAddress      dd      ?
    31.   NumberParameters      dd      ?
    32.   ExceptionInformation  dd EXCEPTION_MAXIMUM_PARAMETERS dup(?)
    33. ends
    34.  
    35. struct  FLOATING_SAVE_AREA
    36.   ControlWord   dd      ?
    37.   StatusWord    dd      ?
    38.   TagWord       dd      ?
    39.   ErrorOffset   dd      ?
    40.   ErrorSelector dd      ?
    41.   DataOffset    dd      ?
    42.   DataSelector  dd      ?
    43.   RegisterArea  db  SIZE_OF_80387_REGISTERS dup(?)
    44.   Cr0NpxState   dd      ?
    45. ends
    46.  
    47. struct  CONTEXT
    48.   ContextFlags  dd      ?
    49.   iDr0          dd      ?
    50.   iDr1          dd      ?
    51.   iDr2          dd      ?
    52.   iDr3          dd      ?
    53.   iDr6          dd      ?
    54.   iDr7          dd      ?
    55.   FloatSave     FLOATING_SAVE_AREA
    56.   regGs         dd      ?
    57.   regFs         dd      ?
    58.   regEs         dd      ?
    59.   regDs         dd      ?
    60.   regEdi        dd      ?
    61.   regEsi        dd      ?
    62.   regEbx        dd      ?
    63.   regEdx        dd      ?
    64.   regEcx        dd      ?
    65.   regEax        dd      ?
    66.   regEbp        dd      ?
    67.   regEip        dd      ?
    68.   regCs         dd      ?
    69.   regFlag       dd      ?
    70.   regEsp        dd      ?
    71.   regSs         dd      ?
    72.   ExtendedRegisters db MAXIMUM_SUPPORTED_EXTENSION dup(?)
    73. ends
    74.  
    75.  
    76. SECTION '.text' CODE EXECUTABLE READABLE
    77. start:
    78.         xor     ebx,ebx
    79.  
    80.         push    SEHhandler
    81.         push    DWORD [fs:ebx]
    82.         mov     [fs:ebx],esp
    83.  
    84.         int3
    85. ;        xchg    [ebx],ebx
    86. ..safe:
    87.         pop     DWORD [fs:ebx]
    88.         pop     edx
    89.  
    90.         invoke  MessageBox,ebx,sMessage1,sCaption1,MB_OK OR MB_ICONINFORMATION
    91.  
    92.         invoke  ExitProcess,ebx
    93.  
    94. proc    SEHhandler c pExceptionRecord:DWORD, pException:DWORD, pContext:DWORD, pDispatcherContext:DWORD
    95.  
    96.         xor     ebx,ebx
    97.         invoke  MessageBox,ebx,sMessage2,sCaption2,MB_OK OR MB_ICONINFORMATION
    98.  
    99.         mov     eax,[pContext]
    100.         mov     [eax + CONTEXT.regEip],..safe
    101.  
    102. ;        invoke  SetThreadContext,-2,[pContext] ; áåç ýòîãî íå ðàáîòàåò, ò.å. çàöèêëèâàåòñÿ íà ýêñåïøåíå!!!
    103.  
    104. ; Ошибка была тут!
    105. ;        mov     eax,EXCEPTION_CONTINUE_EXECUTION
    106.         mov     eax,ExceptionContinueExecution
    107.         ret
    108. endp
    109.  
    110.  
    111. SECTION '.idata' DATA READABLE WRITABLE IMPORT
    112. library kernel32,'KERNEL32.DLL',\
    113.         user32,'USER32.DLL'
    114.  
    115. INCLUDE 'api\kernel32.inc'
    116. INCLUDE 'api\user32.inc'
    117.  
    118.  
    119. SECTION '.rdata' DATA READABLE
    120. sMessage1       TCHAR   'After exception',0
    121. sCaption1       TCHAR   'Repaired',0
    122. sMessage2       TCHAR   'In exception',0
    123. sCaption2       TCHAR   'Repairing',0
    Собсно не работает без явной установки контекста через ф-ю. Что за гон?! XP pre SP3, патчи на ядре и проч муть, связанная с безопасностью...
    файл аттачу для удобства компилирования. Это только у меня так он работате "корректно" или так задумао? Прошу прояснить или ткнуть носом. Спс.
    Ошибка устранена.
     
  7. asmfan

    asmfan New Member

    Blog Posts:
    0
    Пардон, разобрался! Гон был в следующем:
    "Правильные" константы выглядят следующим образом
    А "неправильные"
    фтопку!
    Терь возник другой вопрос - где ж тогда используются те самые "неправильные" константы? Оба варианта можно найти в хедерах... вот вилы то!

    Вопрос снимается - разобрался... точнее съел кашу из головы. Первые используются в мануальном SEH'e, вторые в с нотации __except() и в нек-рых апи. пример ниже.
     
  8. Asterix

    Asterix New Member

    Blog Posts:
    0
    //
    // Exception disposition return values.
    //
    EXCEPTION_DISPOSITION = DWORD;
    const
    ExceptionContinueExecution = 0;
    ExceptionContinueSearch = 1;
    ExceptionNestedException = 2;
    ExceptionCollidedUnwind = 3;

    упс, опоздал, слишком долго была открыта страничка в офлайне прежде чем прочел
     
  9. Twister

    Twister New Member

    Blog Posts:
    0
    Asterix
    Понял. Значит нужно просто сменить EIP и ESP.

    asmfan
    Ну, если учесть, что я пишу на АСМе, а Си не люблю, то наверняка этот вайл у меня есть. ;) Просто я не знал, как называются константы.

    Great
    Ты же прочитал сам вопрос - "вместо валидной инфы вижу порнуху (в обоих случаях получения контекста - см. код)". Так что это было для проверки. Так же в процедуре ThreadProc я, перед вызовом исключения, заношу в регистр EBX значение 0x12345678 - тоже для проверки.

    rain
    В первую очередь. Не прочитав, не полез бы с вопросами.

    Мужики, дык на мой основной вопрос, собственно, ни кто не ответил... :dntknw:
    Попробуйте запустить мой код у себя. По идее, MessageBox должен вывести значение регистра EBX, равное 0x12345678. Но этого не происходит...
     
  10. Asterix

    Asterix New Member

    Blog Posts:
    0
    Именно поэтому ваш пример на Delphi ? ;)


    ваш я не запускал, но мой вроде работает
    Code (Text):
    1. program SEH;
    2. uses
    3.   Windows;
    4. type
    5.   _SEH = record
    6.     SafeEip:DWORD;     // The offset where it's safe to continue execution
    7.     PrevEsp:DWORD;     // The previous value of esp
    8.     PrevEbp:DWORD;     // The previous value of ebp
    9.   end;
    10.  
    11. //
    12. // Exception disposition return values.
    13. //
    14. EXCEPTION_DISPOSITION         =  DWORD;
    15. const
    16.   ExceptionContinueExecution  =  0;
    17.   ExceptionContinueSearch     =  1;
    18.   ExceptionNestedException    =  2;
    19.   ExceptionCollidedUnwind     =  3;
    20.  
    21. var
    22. format_string   : PChar = 'EAX = %08lX' + #0;
    23. __seh           : _SEH;
    24. label   _SafePlace;
    25.  
    26.  
    27. {$O+}
    28. function _except_handler(
    29.     ExceptionRecord:PExceptionRecord;
    30.     EstablisherFrame:Pointer;
    31.     ContextRecord:PContext;
    32.     DispatcherContext:Pointer): EXCEPTION_DISPOSITION; cdecl;
    33. var
    34.  Buff: PChar;
    35.  _EAX: DWord;
    36. begin
    37.   ContextRecord.Eip := __seh.SafeEip;
    38.   ContextRecord.Esp := __seh.PrevEsp;
    39.   ContextRecord.Ebp := __seh.PrevEbp;
    40.   _EAX := ContextRecord.Eax;
    41.   GetMem(Buff, 64);
    42.  asm
    43.    push _EAX
    44.    push format_string
    45.    push Buff
    46.    call wsprintf
    47.    add esp, 0Ch
    48.  end;
    49.   MessageBox(0, Buff, nil, MB_OK or MB_ICONINFORMATION);
    50.   FreeMem(Buff);
    51.   // Tell the OS to restart the faulting instruction
    52.   Result := ExceptionContinueExecution;
    53. end;
    54.  
    55.  
    56. {$O-}
    57. begin
    58.  asm
    59.    push  OFFSET _except_handler
    60.    push  DWORD PTR fs:[0]                 // address of next ERR structure
    61.    mov   fs:[0], esp                      // give FS:[0] the ERR address just made
    62.  
    63.    mov   __seh.SafeEip, OFFSET _SafePlace
    64.    mov   __seh.PrevEsp, esp
    65.    mov   __seh.PrevEbp, ebp
    66.  
    67.    mov eax, $12345678
    68.    db 0CCh
    69.  end;
    70. _SafePlace:
    71.  asm
    72.    pop   DWORD PTR fs:[0]                 // restore next ERR structure to FS:[0]
    73.    add   esp, 4                           // throw away rest of ERR structure
    74.  end;
    75. end.
     
  11. Twister

    Twister New Member

    Blog Posts:
    0
    Asterix
    Немного неверно я выразился. Скажу так - пишу на всем, кроме Сей. На Сях читаю. ;)
    Сейчас пойду тестировать предоставленный вами код. Да, я думаю, все же, не стоит на "Вы" - мы же тут все свои...
     
  12. Twister

    Twister New Member

    Blog Posts:
    0
    Потестировал. Все работает. Так что вопрос можно считать закрытым. Только вот не пойму - а в чем же концептуальная разница между приведенным и моим кодом? Ерунда, вообщем, какая-то...