Перехват прерываний через установку своего обработчика в IDT

Тема в разделе "WASM.NT.KERNEL", создана пользователем SV, 14 дек 2008.

  1. SV

    SV New Member

    Публикаций:
    0
    Регистрация:
    14 дек 2008
    Сообщения:
    3
    Получаю адрес IDT. По (например) седьмому вектору устанавливаю новый обработчик а старый сохраняю в памяти. Т.е в обработчике сохраняются все регистры и флаги, по окончании восстанавливаются регистры и флаги и передается управление на старый обработчик.

    Получения адреса IDT:
    VOID GetIDT(ULONG *ADDR)
    {
    UCHAR idtbase[6];

    _asm
    {
    cli
    pushad

    mov eax,cr0
    push eax
    pop esi
    and eax,0xFFFEFFFF
    mov cr0,eax

    sidt fword ptr [idtbase]
    mov eax,dword ptr [idtbase+2]
    mov edi,ADDR
    mov [edi],eax

    mov cr0,esi
    popad
    sti
    }
    }

    Сохрание и восстановление вектора прерывания:
    void SaveInterruptHandler(ULONG adr_IDT,ULONG InterruptNumber,UCHAR *DataInterrupt)
    {
    _asm
    {
    cli
    pushad

    mov eax,cr0
    push eax
    pop esi
    and eax,0xFFFEFFFF
    mov cr0,eax

    mov ebx,adr_IDT
    mov eax,8
    mov ecx,InterruptNumber
    imul ecx
    add ebx,eax

    mov edi,DataInterrupt
    mov edx,[ebx]
    mov [edi],edx
    mov edx,[ebx+4]
    mov [edi+4],edx

    mov cr0,esi
    popad
    sti
    }
    }

    void RestoreInterruptHandler(ULONG adr_IDT,ULONG InterruptNumber,UCHAR DataInterrupt)
    {
    _asm
    {
    cli
    pushad

    mov eax,cr0
    push eax
    pop esi
    and eax,0xFFFEFFFF
    mov cr0,eax

    mov ebx,adr_IDT
    mov eax,8
    mov ecx,InterruptNumber
    imul ecx
    add ebx,eax

    mov edi,DataInterrupt
    mov edx,[edi]
    mov [ebx],edx
    mov edx,[edi+4]
    mov [ebx+4],edx

    mov cr0,esi
    popad
    sti
    }
    }

    Установка нового вектора прерывания:
    .code
    old_handler dd 0
    data_EXTENSION dd 0

    // обработчик
    InterruptHandler proc
    pushfd
    cli
    pushad
    push es
    push ds
    push fs
    push gs
    mov eax,data_EXTENSION
    ;Вызов из ASM модуля функции InterruptRoutine
    cCall InterruptRoutine,<eax>
    pop gs
    pop fs
    pop ds
    pop es
    popad
    cmp old_handler,0
    je m1
    popfd
    jmp old_handler
    m1: popfd
    iretd
    InterruptHandler endp

    cProc SetInterruptHandler,12,<adr_IDT: dword,InterruptNumber: dword,adr_data: dword>
    cli
    pushad
    mov eax,cr0
    push eax
    pop esi
    and eax,0FFFEFFFFh
    mov cr0,eax

    ;Сохраняется адрес DEVICE_EXTENSION
    mov eax,adr_data
    mov data_EXTENSION,eax

    mov ebx,adr_IDT
    mov eax,8
    mov ecx,InterruptNumber
    imul ecx
    add ebx,eax
    mov edx,0
    mov dx,word ptr [ebx+6]
    shl edx,10h
    mov dx,word ptr [ebx]
    ;Сохраняем в память старый обработчик
    mov old_handler,edx

    mov edx,offset InterruptHandler
    mov word ptr [ebx],dx
    shr edx,10h
    mov word ptr [ebx+6],dx
    mov byte ptr [ebx+5],8eh

    mov cr0,esi
    popad
    sti
    cRet SetInterruptHandler
    endProc SetInterruptHandler
    /*

    Эта функция предназначена для информирования приложения пользователя о произошедшем прерывании (Event)

    */
    void InterruptRoutine(ULONG data)
    {
    PDEVICE_EXTENSION extension=(PDEVICE_EXTENSION)data;
    KIRQL oldIrql;

    KeAcquireSpinLock(&extension->Lock,&oldIrql);

    //Счетчик прерываний
    ++extension->ct;

    KeSetEvent(extension->Event,0,FALSE); // BSOD :dntknw:
    KeClearEvent(extension->Event);

    KeReleaseSpinLock(&extension->Lock,oldIrql);
    }

    Проблема – при вызове KeSetEvent(extension->Event,0,FALSE) происходит BSOD. Подскажите пожалуйста, что я делаю не так (и как надо :)
     
  2. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    Регистрация:
    24 ноя 2006
    Сообщения:
    5.582
    не перезагружаешь селектор FS вероятно на ядреный Селектор PCR
     
  3. vshemm

    vshemm New Member

    Публикаций:
    0
    Регистрация:
    17 мар 2008
    Сообщения:
    10
    На SMP такое работать будет не всегда, нужно делать копию IDT, а не менять существующую (она используется и другими процессорами).
    По хорошему, нужно юзать IoConnectInterrupt().
    Вот тут это неплохо расписано: http://www.codeproject.com/KB/system/soviet_direct_hooking.aspx
    А BSOD то какой?
     
  4. SV

    SV New Member

    Публикаций:
    0
    Регистрация:
    14 дек 2008
    Сообщения:
    3
    Простите за долгое отсутствие.
    Great большое спасибо,все заработало.
    vshemm - спасибо за ссылку. BSOD был завязан с DRIVER_IRQL_LESS_OR_EQUAL.
     
  5. SV

    SV New Member

    Публикаций:
    0
    Регистрация:
    14 дек 2008
    Сообщения:
    3
    Еще один вопрос.Не подскажете как заменить jmp old_handler на call old_handler в своем обработчике через IDT (первым нужно вызвать старый обработчик, а потом свой)

    под DOS WATCOM 32 - работает
    pushfd
    call fword ptr old_handler

    под DOS MICROSOFT 16 - работает
    pushf
    call dword ptr old_handler
     
  6. Mika0x65

    Mika0x65 New Member

    Публикаций:
    0
    Регистрация:
    30 июл 2005
    Сообщения:
    1.384
    Видимо, в новом обработчике должно быть нечто вроде:

    Код (Text):
    1. pushfd
    2. push cs
    3. push new_handler
    4. jmp far [old_handler]