1

Тема: KiGetTickCount -> LDT

Если значение регистра Cs отлично от 0x1B(KGDT_R3_CODE | RPL_MASK), то прерывание 0x2A сводится к вызову NtSetLdtEntries:

KiGetTickCount:
    ...
        push    0                       ; push dummy error code
        ENTER_TRAP      kitx_a, kitx_t
        sti
        xor     eax, eax
        mov     ebx, [ebp+TsEbx]
        mov     ecx, [ebp+TsEcx]
        mov     edx, [ebp+TsEdx]
        stdCall _NtSetLdtEntries <ebx, ecx, edx, eax, eax, eax>
        mov     [ebp+TsEax], eax
        and     dword ptr [ebp+TsEflags], 0FFFFFFFEH ; clear carry flag
        cmp     eax, 0                  ; success?
        je      short ktgc10
        or      dword ptr [ebp+TsEflags], 1 ; set carry flag
ktgc10:
        jmp     _KiExceptionExit

Следующий макрос создаёт дескриптор в лдт:

CREATE_DESCRIPTOR macro Base, Limit
    mov eax,Base
    mov edx,Limit
    mov ecx,eax
    and edx,0F0000H
    shr eax,16
    and ecx,0FF000000h
    and eax,0FFH
    lea edx,[eax + edx + 100H * 11111000B + 100000H * 1100B]    ; Type 100B - code.
    or edx,ecx
    mov eax,Limit
    mov ecx,Base
    and eax,0FFFFH
    shl ecx,16
    lea ecx,[ecx + eax]
; Edx:Ecx
endm

CREATE_LDT_ENTRY macro Selector, Base, Limit
    push ebp
    push ebx
    CREATE_DESCRIPTOR Base, Limit    ; Edx:Ecx
    mov ebp,0F0F0F0F1H
    mov ebx,Selector
    mov eax,ebp
; Eax = Ebp = 0xF0F0F0F1
    Int 2AH    ; KiGetTickCount
; Eax = NTSTATUS
; CF = 0 - STATUS_SUCCESS
    pop ebx
    pop ebp
endm

; Вызов:
TABLE_MASK    equ 100B
    ...
    CREATE_LDT_ENTRY Selector or TABLE_MASK, Base, Limit

Неприятная особенность - нет способа изменить селектор кодового сегмента без вызова NtSetLdtEntries/ProcessLdtInformation. Retf позволяет загрузить теневую часть регистра, но вызов прерывания сбросит её  sad

Отредактировано Indy (2009-10-04 17:57:45)