Пишу простую прогу длЯ защищенного режима. Пока нахожусь в нуливом кольце - все работает отлично, как только менЯю DPL у целивого сегмента с 0 на 3, выскакивает общее нарушение зашиты Вот так все работает: тут таблица дискрипторов: Код (Text): STRUC desc_struc ; структура дескриптора limit dw 0 ; предел base_l dw 0 ; мл. слово физического адреса base_h db 0 ; ст. байт физического адреса access db 0 ; байт доступа acces32 db 0 base_b db 0 ENDS desc_struc ACC_PRESENT EQU 10000000b ; сегмент есть в памџти [hr]ACC_CSEG EQU 00011000b ; сегмент кода ACC_DSEG EQU 00010000b ; сегмент данных ACC_TSSSEG EQU 00001001b ; TSS ACC_EXPDOWN EQU 00000100b ; сегмент расширџетсџ вниз ACC_CONFORM EQU 00000100b ; согласованный сегмент ACC_DATAWR EQU 00000010b ; разрешена запись ACC_INTR_GATE EQU 00001110b ; вентиль прерываниџ ACC_TRAP_GATE EQU 00001111b ; вентиль исключениџ ACC_CALL_GATE EQU 00001100b ACC_TASK_GATE EQU 00000101b ACC_RING0 EQU 00000000b ACC_RING3 EQU 01100000b ; ------------------------------------------------------------ ; ’ипы сегментов DATA_ACC = ACC_PRESENT OR ACC_DSEG OR ACC_DATAWR ; сегмент даннх CODE_ACC = ACC_PRESENT OR ACC_CSEG ; сегмент кода STACK_ACC = ACC_PRESENT OR ACC_DSEG OR ACC_DATAWR OR ACC_EXPDOWN ; сегмент стека TSS_ACC = ACC_PRESENT OR ACC_TSSSEG ; TSS IDT_ACC = DATA_ACC ; байт доступа сегмента таблицы IDT INTR_ACC = ACC_PRESENT OR ACC_INTR_GATE ; байт доступа вентилџ прерываниџ TRAP_ACC = ACC_PRESENT OR ACC_TRAP_GATE ; байт доступа вентилџ исключениџ CALL_ACC = ACC_PRESENT OR ACC_CALL_GATE TASK_ACC = ACC_PRESENT OR ACC_TASK_GATE ACS_GRANUL EQU 10000000b ACS_DIMENS EQU 01000000b DATASEG DSEG_BEG = THIS WORD GDT_BEG = $ LABEL gdtr WORD gdt_0 desc_struc <0,0,0,0,0,0> gdt_gdt desc_struc <GDT_SIZE-1,,,DATA_ACC,0,0> gdt_idt desc_struc <IDT_SIZE-1,,,IDT_ACC,0,0> gdt_ds desc_struc <03fffh,,,DATA_ACC,0,0> gdt_cs desc_struc <03fffh,,,CODE_ACC OR ACC_DATAWR,0,0> gdt_ss desc_struc <03fffh,00000h,000h,DATA_ACC,ACS_DIMENS,0> gdt_ds32 desc_struc <0ffffh,00000h,000h,DATA_ACC OR ACC_RING0,ACS_GRANUL OR 00Fh ,000h> gdt_cs32 desc_struc <0ffffh,00000h,000h,CODE_ACC OR ACC_DATAWR OR ACC_RING0,ACS_GRANUL OR ACS_DIMENS OR 00Fh,000h> gdt_ss32 desc_struc <0ffffh,00000h,000h,DATA_ACC OR ACC_RING0,ACS_GRANUL OR ACS_DIMENS OR 00Fh,000h> gdt_dsdebug desc_struc <0ffffh,00000h,000h,DATA_ACC OR ACC_RING0,ACS_GRANUL OR 00Fh ,000h> gdt_csdebug desc_struc <0ffffh,00000h,000h,CODE_ACC OR ACC_DATAWR OR ACC_RING0,ACS_GRANUL OR ACS_DIMENS OR 00Fh,000h> gdt_all desc_struc <0ffffh,00000h,000h,DATA_ACC OR ACC_RING0,ACS_GRANUL OR 00Fh ,000h> gdt_tds32 desc_struc <0ffffh,00000h,000h,DATA_ACC OR ACC_RING0,ACS_GRANUL OR 00Fh ,000h> gdt_tcs32 desc_struc <0ffffh,00000h,000h,CODE_ACC OR ACC_DATAWR OR ACC_RING0,ACS_GRANUL OR ACS_DIMENS OR 00Fh,000h> gdt_tss32 desc_struc <0ffffh,00000h,000h,DATA_ACC OR ACC_RING0,ACS_GRANUL OR ACS_DIMENS OR 00Fh,000h> gdt_ssdebug desc_struc <0ffffh,00000h,000h,DATA_ACC OR ACC_RING0,ACS_GRANUL OR ACS_DIMENS OR 00Fh,000h> gdt_pzu desc_struc <007ffh,00000h,080h,DATA_ACC OR ACC_RING0,ACS_GRANUL OR 000h ,0ffh> gdt_cpzu desc_struc <007ffh,00000h,000h,DATA_ACC OR ACC_RING0,ACS_GRANUL OR 000h ,0ffh> gdt_ramq desc_struc <003ffh,00000h,000h,DATA_ACC OR ACC_RING0,ACS_GRANUL OR 000h ,080h> gdt_ramx desc_struc <003ffh,00000h,080h,DATA_ACC OR ACC_RING0,ACS_GRANUL OR 000h ,080h> gdt_ramy desc_struc <003ffh,00000h,000h,DATA_ACC OR ACC_RING0,ACS_GRANUL OR 000h ,081h> gdt_ramz desc_struc <003ffh,00000h,080h,DATA_ACC OR ACC_RING0,ACS_GRANUL OR 000h ,081h> gdt_tss_main desc_struc <06bh,,,TSS_ACC,0,0> gdt_tss_task1 desc_struc <06bh,,,TSS_ACC,0,0> gdt_tss_task2 desc_struc <06bh,,,TSS_ACC,0,0> gdt_tss_task3 desc_struc <06bh,,,TSS_ACC,0,0> gdt_tss_task4 desc_struc <06bh,,,TSS_ACC,0,0> gdt_ds1 desc_struc <00001h,00000h,000h,DATA_ACC OR ACC_RING3,ACS_GRANUL OR 000h ,000h> gdt_cs1 desc_struc <00002h,00000h,000h,CODE_ACC OR ACC_DATAWR OR ACC_RING0,ACS_GRANUL OR ACS_DIMENS OR 000h,000h>;селектор 0e0h gdt_ss1 desc_struc <00003h,00000h,000h,DATA_ACC OR ACC_RING3,ACS_GRANUL OR ACS_DIMENS OR 000h,000h> далее перехожу в защищенный режим, инициализирую gdt_cs1 (адрес в памЯти, предел), в нем по адресу 01010h размещаю код: Код (Text): stlbpnt PROC far mov dx, 1070h mov eax,055h out dx, eax hlt ret stlbpnt ENDP порт 1070h - введен спецально длЯ отладки (это нестандартнаЯ ЏЉ). далее перехожу непосредственно на этот код: Код (Text): DB 09ah DD 01010h DW 0e0h по завершению из порта 1070h читаю 55h. Сдесь все работает на ура. А так нет: ввожу изменениЯ: Код (Text): ... gdt_cs1 desc_struc <00002h,00000h,000h,CODE_ACC OR ACC_DATAWR OR ACC_RING3,ACS_GRANUL OR ACS_DIMENS OR 000h,000h>;селектор 0e3h ... DB 09ah DD 01010h DW 0e3h После чего сразу выскакивает исключение 13. Порт 1070h остаетсЯ без изменений. Что сдесь нетак?
Цитата из intel manual: The JMP instruction cannot be used to perform inter-privilege-level far jumps. Для перехода в сторону увеличения CPL предлагаю использовать retf, iret. И IOPL = 3? А то in/out сгенерят #GP(0)
про IOPL в EFLAGS, незнал ,спасибо, проверю. заменю на ячейку памяти, коль одна и таже прерва. Про CALL: т.е. я прямым вызовом нимогу вызвать целевой сегмент с меньшим уровнем привилегей из сегмента с большими привилегиями?????, я в шоке и как быть? что делать?
Как сказал JAPH -- использовать iret/retf, предаврительно сформировав корректные eflags, ss, esp, cs, eip/ss, esp, cs, eip в стеке.
т.е. понизить привилегии гораздо сложнее чем повысить( для повышения делаем шлюз и все ОК), а для понижения нигде неописаный танец с бубноп? (( чото это както кривовато....... по суте цель защиты - выполнить на привелигированном уровне необходимые действа и передать управление менее превилигированному коду, для которого делегировать некоторые функции через шлюзы и т.д.
Попытался сделать через TSS, все тоже, на без понижения привилегии(ring0), все работает, при понижении до ring3 - все умирает, теперь даже без исключения
Если бы здесь не исчезали посты, то ты бы уже давно увидел, что я сказал, что ret/iret не "както кривовато", а вполне даже нормально, поэтому не нужно выискивать какие-то другие способы.
Абсолютно правильно. Других документированных способов фактически нет. Переключение задач формально позволяет передать управление на коду с мЕньшим CPL, но по сути это не совсем то, т.к. меняется контекст проца. Sysexit тоже не подходит, т.к. позволяет только r0->r3. R2->r3, к примеру уже не пройдет
Поздравляю. Вот только что получится, если оценивать производительность этого способа по сравнению с обычным.