среда, 25 января 2012 г.

Когда postmortem analysis бесполезен

Чаще всего при BSOD'ах помогает анализ креш дампа, но бывают случаи, когда такой анализ бесполезен.

Такие ситуации могут быть, когда существует системный поток или воркитем, которые по каким-то причинам ( ошибки в проектировании )
продолжают работать даже тогда, когда драйвер выгружен, что приводит к ошибкам доступа к выгруженной памяти и соответственно к багчеку:

DRIVER_UNLOADED_WITHOUT_CANCELLING_PENDING_OPERATIONS (ce)
A driver unloaded without cancelling timers, DPCs, worker threads, etc.
The broken driver's name is displayed on the screen.
Arguments:
Arg1: f7e7f81a, memory referenced
Arg2: 00000008, value 0 = read operation, 1 = write operation
Arg3: f7e7f81a, If non-zero, the instruction address which referenced the bad memory
    address.
Arg4: 00000000, Mm internal code.

Debugging Details:
------------------

WRITE_ADDRESS:  f7e7f81a

FAULTING_IP:
Template+181a
f7e7f81a ??              ???
...
PROCESS_NAME:  System
...

STACK_TEXT: 
f7f5a84c 804f7bad 00000003 f7e7f81a 00000000 nt!RtlpBreakWithStatusInstruction
f7f5a898 804f879a 00000003 00000000 c07bf3f8 nt!KiBugCheckDebugBreak+0x19
f7f5ac78 804f8cc5 00000050 f7e7f81a 00000008 nt!KeBugCheck2+0x574
f7f5ac98 8051cc5f 00000050 f7e7f81a 00000008 nt!KeBugCheckEx+0x1b
f7f5acf8 8054052c 00000008 f7e7f81a 00000000 nt!MmAccessFault+0x8e7
f7f5acf8 f7e7f81a 00000008 f7e7f81a 00000000 nt!KiTrap0E+0xcc
WARNING: Frame IP not in any known module. Following frames may be wrong.
f7f5ad80 00000000 8162dd80 00000000 00000000 <Unloaded_Template.sys>+0x181a

В этом случае из дампа невозможно понять кто виноват, т.к. доступа к памяти с драйвером нет, она не валидна:

kd> !pte f7e7f81a
                    VA f7e7f81a
PDE at C0603DF8            PTE at C07BF3F8
contains 000000000101F163  contains 0000000000000000
pfn 101f      -G-DA--KWEV   not valid

Когда системный поток или воркитем один, то логика нас приводит к анализу именно его. Но что делать, когда их несколько?

Очевидно, что тут потребуется live анализ и выявление границ функций системных потоков на рабочем драйвере.

Смотрим в исходниках имя системного потока и имя следующей за ним функции, пусть к примеру это будет SystemThread1 и InitSystemThread1, тоже самое делаем для остальных потоков.

Далее в отладчике на живом запущенном драйвере находим границы ф-ции системных потоков:

kd> ? InitSystemThread1 - SystemThread1
Evaluate expression: 336 = 00000150 - размер ф-ции

Выводим листинг всей ф-ции:

kd> u f77fd6f0 f77fd6f0+150h

f77fd6f0 55              push    ebp
f77fd6f1 8bec            mov     ebp,esp
f77fd6f3 6aff            push    0FFFFFFFFh
f77fd6f5 68d81180f7      push    offset Template!__safe_se_handler_table+0x8 (f78011d8)
f77fd6fa 6808dd7ff7      push    offset Template!except_handler3 (f77fdd08)
f77fd6ff 64a100000000    mov     eax,dword ptr fs:[00000000h]
f77fd705 50              push    eax
...

Делаем тоже самое для остальных потоков, после чего добиваемся воспроизведения BSOD'а.

После чего, обладая асм листингами всех рабочих потоков, легко можно будет найти виновника торжества и устранить проблему.

Комментариев нет:

Отправить комментарий