В DriverEntry в регистре Cs флаг TI=1, значит код выполняется из сегмента описаного в LDT, в скрытой части регистра Cs содержится база сегмента - выходит что процессору не обязательно знать линейный адрес GDT чтобы выполнить мою DriverEntry и тот код который вызвал DriverEntry ? Выходит что из DriverEntry база хранящаяся в регистре GDTR может отображатся (в контексте данного процесса) на совсем другие физические страницы, тоесть не те где действительно записана GDT ? Тоесть тот код, назовём его планировщиком, который вызвал ту функцию которая вызвала мою DriverEntry мог изменить регистр CR3(PDBR) где хранится Page Directory отображающая базу GDT на физические страницы в контексте планировщика ? И ещё, какой тогда смысл в содержимом fs:3Ch - KPCR (KGDTENTRY*) GDT ?
Charlief Дескриптор TSS может быть только в GDT. Иначе трап-процессинг работать не будет(при смене CPL камень уйдёт в ступор или сгенерит #DF). PCR это блок содержащий инфу уникальную для процессора, в частности базы GDT, IDT, TSS.
Clerk Спасибо за информацию. Линейный адрес сегмента TSS не даёт информации о расположении GDT. А вот указатель в KPCR на GDT-entry - это только копия дескриптора из GDT или это собственно и есть сама GDT (так сказать непосредственная часть её тела) ? - вы имли в виду KGDTENTRY* и KIDTENTRY* ?
Clerk - это я знаю, просто (я в первом сообщении написал) я думал что эта база может быть не действительна в контексте моего драйвера. Кажется всё прояснилось, похоже что база GDT в GDTR - это виртуальный адрес в адрессном пространстве моего драйвера, совпадает с полем GDT в KPCR. DebugView: 00000000 0.00000000 DriverEntry 00000001 0.00000166 00000002 0.00000299 Cs=b704 00000003 0.00000420 GDTR Limit=3ff 00000004 0.00000556 GDTR Base=ba34c190 00000005 0.00000639 00000006 0.00000771 KPCR SelfPcr=ba348000 00000007 0.00000861 00000008 0.00000990 KPCR IDT=ba34c590 00000009 0.00001116 KPCR GDT=ba34c190 00000010 0.00001238 KPCR TSS=ba348d70 Спасибо за помощь !!!
Clerk В obj файле скомпилированом NASM: Код (Text): _AReadCsGDTR@4: mov eax, [esp+4] mov WORD [eax], cx sgdt [eax+2] ret 4 В DriverEntry: Код (Text): ... AReadCsGDTR(&sCsGDTR); ... DbgPrint("Cs=%x", sCsGDTR.Cs); ... Что-то не так ?
Clerk Тоесть мне скопировать содержимое всех регистров из DriverEntry - написать такую прцедуру на ассемблере ? А что ещё кроме регистров ? Где можно прочитать что ещё нужно копировать ?
Кажется я нашёл причину, все вызовы своих функций у меня были помещены внутри блока __try. Убрал всё оттуда, вот что вышло: DebugView: 00000000 0.00000000 DriverEntry 00000001 0.00000156 00000002 0.00000287 Cs=e64e 00000003 0.00000409 GDTR Limit=3ff 00000004 0.00000548 GDTR Base=8003f000 00000005 0.00000631 00000006 0.00000757 KPCR SelfPcr=ffdff000 00000007 0.00000842 00000008 0.00000971 KPCR IDT=8003f400 00000009 0.00001092 KPCR GDT=8003f000 00000010 0.00001214 KPCR TSS=80042000 Затем снова всё поместил в болк __try DebugView: 00000000 0.00000000 DriverEntry 00000001 0.00000152 00000002 0.00000285 Cs=b704 00000003 0.00000407 GDTR Limit=3ff 00000004 0.00000546 GDTR Base=8003f000 00000005 0.00000631 00000006 0.00000758 KPCR SelfPcr=ffdff000 00000007 0.00000844 00000008 0.00000968 KPCR IDT=8003f400 00000009 0.00001090 KPCR GDT=8003f000 00000010 0.00001214 KPCR TSS=80042000 Наверное какое-то переключение контекста внутри __try если cs меняется...
0x6b65 Какая ещё опечатка ? Вы о чем ? Где опечатка ? Я в функцию передаю адрес структуры, а потом по этому адресу записываю CS ! Эта функция ничего не возвращает в регистре ax, смотрите выше код на С++. IDA: Код (Text): ; __stdcall AReadCsGDTR(x) public _AReadCsGDTR@4 _AReadCsGDTR@4 proc near arg_0= dword ptr 4 mov eax, [esp+arg_0] mov [eax], cx sgdt fword ptr [eax+2] retn 4 _AReadCsGDTR@4 endp 2.2.3 NASM не хранит типы переменных NASM не запоминает определямые вами типы переменных. Поскольку MASM эти вещи запоминает, то при встрече var dw 0 он запомнит, что вы определили var как пременную размером в слово и затем будет способен разрешить неопределенность при появлении инструкции mov var,2. NASM же преднамеренно не будет помнить ничто относительно символа var за исключением того, где он начинается, поэтому вы должны явно указывать mov word [var],2.
Charlief Значение селектора больше чем лимит GDT. Уверен что LDTR(селектор дескриптора LDT в GDT) = 0. Это инвалидные данные. Опкод mov word ptr ds:[eax],cs: 8C 08. Вы читаете регистр Cx.
Теперь Cs=8. Ещё наверное нужно в драйвере в прототипе импортируемой ассемблерной функции указывать что она что-то возвращает если я в этой функции перед использованием eax не сохраняю его в стеке ? Тогда компилятор С++ поймёт что я затираю eax ? Так сказать во избежание всяких неприятностей.