1) Запутался в сегментах, селекторах, дескрипторах... Как вычислить ФИЗИЧЕСКИЙ адрес какой-нибудь переменной (кода) в защищённом режиме в плоской модели, в страничной? 2) См. приложение. Находит ли этот код реальный адрес IDT и обработчика прерывания № 32? Если нет, то подскажите, пожалуйста, как вычислить его физический адресс. Написано на FASM'e. 3) Ну, и вытекает из п.1 и 2, как подменить обработчик прерывания? Спасибо всем откликнувшимся! Приложение: sidt [idt] mov eax,idt mov eax,[eax+2] ;line address for IDT table lea ecx,[eax+32*8] ;line address for int0 handler mov eax,[ecx+4] ;селектор(31-16),смещение(15-0) xor ax,ax mov ax,[ecx] ;смещение (31-16) idt dp ?
staper Если под защищённым режимом с плоской моделью и страничной адресацией подразумевается Windows, то там преравания, кроме int 2Eh не используются
Mikl___ Если под "используюся" подразумевается "установлены" и под прерываниями подразумеваются программные прерывания, то кроме 2e есть еще 2a - KiGetTickCount 2b - KiCallbackReturn 2c - KiSetLowWaitHighThread 2d - KiDebugService Используются из них 2e: (в win 2k), 2b: возврат из каллбеков (в которые зашли по KeUserModeCallback), 2d: nt!DbgPrint -> nt!vDbgPrintExWithPrefix -> nt!DebugPrint -> nt!DebugService -> int 2dh staper Ну примерно так. Код (Text): // // IDT entry // #pragma pack(push, 1) typedef struct { USHORT OffsetLow; USHORT Selector; UCHAR ReservedByte; UCHAR Type : 3; UCHAR D : 1; UCHAR UnusedBits2 : 1; UCHAR DPL : 2; UCHAR Present : 1; USHORT OffsetHigh; } IDTEntry, *PIDTEntry; #pragma pack(pop) // // IDTR register // #pragma pack(push, 2) typedef struct { USHORT Limit; PIDTEntry Table; } IDTR, *PIDTR; #pragma pack(pop) // // Routines to work with IDT // IDTR Idtr; PVOID SetVector( IN UCHAR Interrupt, IN PVOID Handler, IN BOOLEAN MakeValid ) /** Set IDT vector Interrupt to point to Handler */ { BOOLEAN OldWP; ULONG OldHandler; KIRQL Irql; // // Disable WP and interrupts // OldWP = DisableWP(); Irql = KfRaiseIrql (HIGH_LEVEL); if (Idtr.Table == NULL) __asm sidt fword ptr [Idtr] // // Fill out IDT entry with the corresponding values // OldHandler = Idtr.Table[Interrupt].OffsetLow | ( Idtr.Table[Interrupt].OffsetHigh << 16 ); Idtr.Table[Interrupt].OffsetLow = (USHORT) ( (ULONG)Handler ) & 0xFFFF; Idtr.Table[Interrupt].OffsetHigh = (USHORT) ( (ULONG)Handler >> 16 ) & 0xFFFF; if (MakeValid) { Idtr.Table[Interrupt].Present = 1; Idtr.Table[Interrupt].D = 1; Idtr.Table[Interrupt].DPL = 3; Idtr.Table[Interrupt].Selector = 0x0008; } // // Restore interrupts and CR0 value // KfLowerIrql (Irql); RestoreWP (OldWP); return (PVOID) OldHandler; }
staper, рекомендую мануалы от интела. там даже картинки со стрелочками, которые показывают что откуда и куда поставить, чтоб сконвертить адрес из одного вида в другой. код грейта исчо надо бы на каждом йадре выполнить, но это мелочи
staper - для записи в IDT физический адрес знать не надо. В IDT хранятся логические адреса обработкиков: selector:offset А вообще преобразование такое: logical_address->linear_address->physical_address 1. logical_address->linear_address из GDT/LDT в зависимости от селектора читаем базовый адрес сегмента и к нему прибавляем смещение. получаем линейный адрес 2. linear_address->physical_address для линейного адреса считаем номер страницы page_num=linear_address / page_size и смещение в странице page_offset=linear_address % page_size По номеру страницы (page_num) из таблицы страниц читаем физический адрес страницы и к нему прибавляем смещение в странице (page_offset). Получаем физический адрес. Если страничная адресация не включена - физический адрес равен линейному.