SEH в ядре

Тема в разделе "WASM.WIN32", создана пользователем Awk, 15 май 2006.

  1. Awk

    Awk New Member

    Публикаций:
    0
    Регистрация:
    8 апр 2006
    Сообщения:
    8
    Я пишу драйвер, который читает память модулей режима ядра. В него входит функция:


    Код (Text):
    1. bool SafeRead(void* Dest, const void* Src, size_t Count)
    2. {
    3.     bool bOk = true;
    4.     __try
    5.     {
    6.         DbgPrint("Reading 0x%X-0x%X\n", Src, ((PBYTE)Src) + Count - 1);
    7.         RtlCopyMemory(Dest, Src, Count);
    8.     }
    9.     __except(EXCEPTION_EXECUTE_HANDLER)
    10.     {
    11.         bOk = false;
    12.     }
    13.     return bOk;
    14. }




    Когда читаю этой функцией секцию INIT (которая discardable), при копировании возникает исключение PAGE_FAULT_IN_NONPAGED_AREA, которое почему-то приводит к BSOD, вместо того, чтобы передать управление обработчику.



    При этом вещи вроде чтения нулевого указателя она обрабатывает корректно (заходит в обработчик).



    В программе используются C++ исключения (громко сказано, просто добавлен заглушечный


    Код (Text):
    1. extern "C" EXCEPTION_DISPOSITION __cdecl __CxxFrameHandler
    2. (
    3.  _EXCEPTION_RECORD *ExceptionRecord,
    4.  void * EstablisherFrame,
    5.  _CONTEXT *ContextRecord,
    6.  void * DispatcherContext
    7.  )
    8. {
    9.     KeBugCheckEx(0xCCEC, 0, 0, 0, 0);
    10.     return ExceptionContinueSearch;
    11. }




    чтобы STL компилировалось).
     
  2. trash

    trash New Member

    Публикаций:
    0
    Регистрация:
    9 апр 2006
    Сообщения:
    143
    Адрес:
    х.з.
    Перехватывай исключения на уровне прерываний - (перепеши IDT).



    А то все эти FS:0, не серьезные какието..



    BSOD by PAGE_FAULT_IN_NONPAGED_AREA разве это ни очем не говорит?



    А так делаешь CLI переписываешь IDT, и вперед.. Если Int сработал - значит не повезло... Востанавливаеш его обратно и выходишь.
     
  3. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    А если так:


    Код (Text):
    1. bool SafeRead(void* Dest, const void* Src, size_t Count){
    2.     bool bOk;
    3.     __try {
    4.         DbgPrint("Reading 0x%X-0x%X\n", Src, ((PBYTE)Src) + Count - 1);
    5.         char probe = *((PCHAR*)Src);
    6.         probe = *((PCHAR*)Src + Count - 1);
    7.     }
    8.     __except(EXCEPTION_EXECUTE_HANDLER) return false;
    9.     RtlCopyMemory(Dest, Src, Count);
    10.     return true;
    11. }
    12.  
     
  4. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    А вызывать MmIsAddressValid не пробовал?
     
  5. trash

    trash New Member

    Публикаций:
    0
    Регистрация:
    9 апр 2006
    Сообщения:
    143
    Адрес:
    х.з.
    Да и еще вот - раз такая тема как память сканировать...



    В GDT энтяры наверно есть место для прописки своих дескрипторов?



    Там можно установить 4Гб нелимит и чтоб без пэйджа и чтоб адреса совпадали с физическим, чтобы тем самым сканировать адреса начиная с 0?
     
  6. Awk

    Awk New Member

    Публикаций:
    0
    Регистрация:
    8 апр 2006
    Сообщения:
    8
    cresta, спасибо, MmIsAddressValid - скорее всего, то, что нужно (вернусь домой - перепроверю, но в этой статье тоже пишут о необходимости его вызова).

     
  7. z0mailbox

    z0mailbox z0

    Публикаций:
    0
    Регистрация:
    3 фев 2005
    Сообщения:
    635
    Адрес:
    Russia СПБ
    SEH-и в kernel-mode ненадежны



    вот такой сработает:



    __try

    {

    PULONG ptr = NULL;

    ULONG bad = *ptr;

    }

    __except(EXCEPTION_EXECUTE_HANDLER)

    {

    }



    а такой - нет. будет синька



    __try

    {

    PULONG ptr = NULL-1;

    ULONG bad = *ptr;

    }

    __except(EXCEPTION_EXECUTE_HANDLER)

    {

    }



    надо сразу писАть так чтоб не падало ну почти никогда
     
  8. trash

    trash New Member

    Публикаций:
    0
    Регистрация:
    9 апр 2006
    Сообщения:
    143
    Адрес:
    х.з.
    Ерунда ваша заливная рыба!

    Вот так поэкстремальней будет...
    Код (Text):
    1.  
    2. {$apptype console}
    3. program CpuClk; uses windows;
    4. procedure printf(a:pchar;b:integer);cdecl;external 'crtdll.dll' name 'printf';
    5.  
    6. type IDT_descriptor = packed record
    7. case integer of
    8.  
    9.   1:(offset_15_0    : word;
    10.      selector       : word;
    11.      reserved       : byte;
    12.      attrib         : byte;
    13.      offset_31_16   : word;);
    14.   2:(int64 : int64)
    15. end;
    16.  
    17.     interrupt  = array [0..255] of IDT_descriptor;
    18.  
    19.     var hDrv, b, TimerHi, TimerLo : DWORD;
    20.  
    21.     idt: packed record
    22.     leng:word;
    23.     (* union *) case integer of
    24.     1:( base:integer);
    25.     2:( interrupt:^interrupt );
    26.     end; //end;
    27.  
    28.     old_vect : array [0..128] of int64;
    29.  
    30. var  _esp, int_proc:cardinal; _R_:integer = 0; i : byte;
    31.  
    32. procedure Ring0;
    33. label todo;
    34. begin
    35. //procedure int_dispatch;assembler;
    36. //asm
    37. //end;
    38. //_r_ := 255;
    39. //exit;
    40. asm
    41. mov eax, offset @00
    42. mov int_proc, eax
    43. jmp @@start
    44. @00: mov al, 00h; jmp @@exit;{Divide Error}
    45. @01: mov al, 01h; jmp @@exit;{Debug Exception}
    46. @02: mov al, 02h; jmp @@exit;{NMI Interrupt}
    47. @03: mov al, 03h; jmp @@exit;{Breakpoint}
    48. @04: mov al, 04h; jmp @@exit;{INTO-detected Overflow}
    49. @05: mov al, 05h; jmp @@exit;{BOUND Range Exceeded}
    50. @06: mov al, 06h; jmp @@exit;{Invalid Opcode}
    51. @07: mov al, 07h; jmp @@exit;{Device Not Available}
    52. @08: mov al, 08h; jmp @@exit;{Double Fault}
    53. @09: mov al, 09h; jmp @@exit;{CoProcessor Segment Overrun (reserved)}
    54. @10: mov al, 0Ah; jmp @@exit;{Invalid Task State Segment}
    55. @11: mov al, 0Bh; jmp @@exit;{Segment Not Present}
    56. @12: mov al, 0Ch; jmp @@exit;{Stack Fault}
    57. @13: mov al, 0Dh; jmp @@exit;{General Protection}
    58. @14: mov al, 0Eh; jmp @@exit;{Page Fault}
    59. @15: mov al, 0Fh; jmp @@exit;{Intel reserved. Do not use}
    60. @16: mov al, 10h; jmp @@exit;{Floating-Point Error}
    61. @17: mov al, 11h; jmp @@exit;{Alignment Check}
    62. @18: mov al, 12h; jmp @@exit;{Machine Check*}
    63. @19: mov al, 13h; jmp @@exit;
    64. @@exit:
    65. mov _R_ , eax
    66. mov esp, _esp
    67. jmp todo
    68. @@start:
    69. end;
    70.      //Вырубить прерывания, считать указатель IDT
    71.      asm cli; sidt[idt] end; //exit;
    72.      //Сохранить вектора исключительных прерываний
    73.      for i:=0 to 32 do old_vect[i] := idt.interrupt[i].int64;
    74.      //Переустановить IDT
    75.      for i := 0 to 19 do
    76.      begin
    77.       idt.interrupt[i].offset_15_0  := int_proc;
    78.       idt.interrupt[i].offset_31_16 := int_proc shr 16;
    79.       idt.interrupt[i].selector     := 8;
    80.       idt.interrupt[i].attrib := $8E {dpl0, interrupt_gate_type};
    81.       int_proc := int_proc + 4;
    82.      end;  
    83.      //
    84.      asm  mov _esp, esp; db 90h,90h,90h,90h end;
    85.      //сделать падже фаулт
    86.      asm  xor eax, eax; mov eax, cs:[eax]
    87.      end;
    88.  
    89. todo://восстановить всю хрень
    90.      for i:=0 to 32 do idt.interrupt[i].int64 := old_vect[i];
    91.     //и выйти
    92. end;
    93.  
    94. begin
    95.  hDrv := CreateFileA ('\\.\\MicroDrv', $80000000, 0, nil, 3, $80, 0);
    96.     DeviceIoControl ( hDrv,  0,  @Ring0, 4, @Ring0, 0, b, nil);
    97.  printf ('%X ', _R_);//TimerLo);
    98.  
    99. CloseHandle (hdrv);
    100. end.
    101.  
     
  9. Ms Rem

    Ms Rem New Member

    Публикаций:
    0
    Регистрация:
    17 апр 2005
    Сообщения:
    1.057
    Адрес:
    С планеты "Земля"
    Юзай MmIsAddressValid, т.к. сех не отлавливает исключения в nonpaged pool.
     
  10. trash

    trash New Member

    Публикаций:
    0
    Регистрация:
    9 апр 2006
    Сообщения:
    143
    Адрес:
    х.з.
    вобщем DS:[0] генерит 0E (Page Fault), а DS:[-1] вызывает 0D -GPF.