nt!KeWaitForSingleObject без аргументов

В настоящее время я пытаюсь отладить системный тупик, и мне трудно понять это.

Child-SP          RetAddr           : Args to Child                                                           : Call Site
fffff880`035cb760 fffff800`02ecef72 : 00000000`00000002 fffffa80`066e8b50 00000000`00000000 fffffa80`066a16e0 : nt!KiSwapContext+0x7a
fffff880`035cb8a0 fffff800`02ee039f : fffffa80`0b9256b0 00000000`000007ff 00000000`00000000 00000000`00000000 : nt!KiCommitThreadWait+0x1d2
fffff880`035cb930 fffff880`0312a5e4 : 00000000`00000000 fffff800`00000000 fffffa80`079a3c00 00000000`00000000 : nt!KeWaitForSingleObject+0x19

Почему первый аргумент для KeWaitForSingleObject будет нулевым?

Если только я не неправильно понял, разве это не первый аргумент, от которого ожидают объекта? Является ли тупик просто тем, что этот поток ничего не ждет или это обычное поведение?

Дополнительно я вижу другой процесс (services.exe), показывающий похожую трассировку стека:

1: kd> .thread fffffa800d406b50
Implicit thread is now fffffa80`0d406b50
1: kd> kv
  *** Stack trace for last set context - .thread/.cxr resets it
Child-SP          RetAddr           : Args to Child                                                           : Call Site
fffff880`09ed4800 fffff800`02ecef72 : fffffa80`0d406b50 fffffa80`0d406b50 00000000`00000000 fffff8a0`00000000 : nt!KiSwapContext+0x7a
fffff880`09ed4940 fffff800`02ee039f : 00000000`000000b4 fffffa80`0b1df7f0 00000000`0000005e fffff800`031ae5e7 : nt!KiCommitThreadWait+0x1d2
fffff880`09ed49d0 fffff800`031d1e3e : fffffa80`0d406b00 00000000`00000006 00000000`00000001 00000000`093bf000 : nt!KeWaitForSingleObject+0x19f
fffff880`09ed4a70 fffff800`02ed87d3 : fffffa80`0d406b50 00000000`77502410 fffff880`09ed4ab8 fffffa80`0b171a50 : nt!NtWaitForSingleObject+0xde

Эта нить ждет сама по себе?

2 ответа

Решение

Вы отлаживаете 64-битный процесс.

Помните соглашение о вызовах x64, которое объясняется здесь. Первые 4 аргумента передаются в регистрах. После этого аргументы помещаются в стек.

К несчастью, kv вслепую отображает аргументы стека. На самом деле, было бы довольно сложно (а иногда и невозможно) определить, какими были первые 4 аргумента на самом деле во время вызова, так как они, возможно, не были сохранены где-либо, что когда-либо может быть восстановлено.

Итак, вы смотрите на 5-й аргумент nt!NtWaitForSingleObject, где nullptr довольно типичный аргумент для Timeout,

К счастью для нас, типы отладки, еще не все потеряно! Существует расширение windbg, которое делает все возможное для восстановления аргументов при вызове функции. Расширение называется CMKD. Вы можете разместить расширение DLL в вашем winext папку и назовите это так:

0:000> !cmkd.stack -p
Call Stack : 7 frames
## Stack-Pointer    Return-Address   Call-Site       
00 000000a408c7fb28 00007ffda95b1148 ntdll!NtWaitForSingleObject+a 
    Parameter[0] = 0000000000000034
    Parameter[1] = 0000000000000000
    Parameter[2] = 0000000000000000
    Parameter[3] = (unknown)       
01 000000a408c7fb30 00007ff7e44c13f1 KERNELBASE!WaitForSingleObjectEx+98 
    Parameter[0] = 0000000000000034
    Parameter[1] = 00000000ffffffff
    Parameter[2] = 0000000000000000
    Parameter[3] = 00007ff7e44cba28
02 000000a408c7fbd0 00007ff7e44c3fed ConsoleApplication2!main+41 
    Parameter[0] = (unknown)       
    Parameter[1] = (unknown)       
    Parameter[2] = (unknown)       
    Parameter[3] = (unknown)       

Обратите внимание, что не всегда удается найти аргумент, так как некоторые из них (unknown), Но он делает довольно хорошую работу и может быть бесценным инструментом при отладке 64-битного кода.

Это похоже на 64-битную ОС, и поэтому соглашение о вызовах не должно передавать все параметры в стеке. Скорее, первые четыре параметра передаются в RCX, RDX, R8 и R9, а остальные параметры в стеке. Так что, если вы перехватите вызов KeWaitForSingleObject, легко увидеть, что находится в RCX, и идти дальше. После того, как вы пройдете несколько стековых фреймов, это будет трудно сказать, так как что-то будет загружено в этот регистр. Исходное значение, вероятно, где-то хранится, но его будет сложно найти.

Другие вопросы по тегам