Предположим, перехвачена ф-ция на уровне менеджера объектов, к примеру ObCreateObject.
Как определить, какая сервисная ф-ция вызвала перехваченную ObCreateObject?
Ну, логично брякнуться внутри перехваченной ф-ции, и посмотреть стек вызовов:
kd> k
ChildEBP RetAddr
ee6aece0 f7966345 Template!InternalObCreateObject+0xee
ee6aece4 8060528e Template!NewObCreateObject+0x5
ee6aed48 8053d648 nt!NtCreateEvent+0x90
ee6aed48 7c90e514 nt!KiFastCallEntry+0xf8
00abfd74 7c90d09a ntdll!KiFastSystemCallRet
00abfd78 7c80a78a ntdll!NtCreateEvent+0xc
00abfdc4 76d525a0 kernel32!CreateEventW+0x67
WARNING: Frame IP not in any known module. Following frames may be wrong.
00abfe68 7c917719 0x76d525a0
00abffa0 77de354b ntdll!LdrpGetProcedureAddress+0xa6
00abffbc 00000000 ADVAPI32!ScSvcctrlThreadA+0x12
А дальше казалось бы, логично проделать теже действия, что и WinDbg, и достать id из стаба ntdll, т.е. выполнить стек бектрейс, например, используя RtlCaptureStackBackTrace. И все бы хорошо, но данная ф-ция вернет лишь три верхних строчки из приведенного лога. И это понятно, т.к. ф-ция прыгает по цепочкам ebp фреймов, но допрыгать ф-ция может лишь до места, где копируется юзермодный стек в ядерный ( в обработчике sysenter ).
Где же взять информацию о юзермодном стеке? Ответ прост: в трап фрейме:
kd> dt nt!_KTRAP_FRAME 0xee6aed64
...
+0x070 EFlags : 0x202
+0x074 HardwareEsp : 0xabfd78 <========== юзермодный стек
+0x078 HardwareSegSs : 0x23
а вот и то, что нужно:
kd> dds 0xabfd78
00abfd78 7c90d09a ntdll!NtCreateEvent+0xc
00abfd7c 7c80a78a kernel32!CreateEventW+0x67
kd> u 7c90d09a
ntdll!NtCreateEvent+0xc:
7c90d09a c21400 ret 14h
7c90d09d 90 nop
Теперь можно прочитать id:
kd> u NtCreateEvent
ntdll!ZwCreateEvent:
7c90d08e b823000000 mov eax,23h <== id
7c90d093 ba0003fe7f mov edx,offset SharedUserData!SystemCallStub (7ffe0300)
7c90d098 ff12 call dword ptr [edx]
7c90d09a c21400 ret 14h
То есть, бектрейс в данном случае оказался совсем не нужным.
На х64 все еще проще, id сискола сохраняется в KTHREAD_SystemCallNumber(название по памяти пишу, могу ошибаться в имени поля).
Как определить, какая сервисная ф-ция вызвала перехваченную ObCreateObject?
Ну, логично брякнуться внутри перехваченной ф-ции, и посмотреть стек вызовов:
kd> k
ChildEBP RetAddr
ee6aece0 f7966345 Template!InternalObCreateObject+0xee
ee6aece4 8060528e Template!NewObCreateObject+0x5
ee6aed48 8053d648 nt!NtCreateEvent+0x90
ee6aed48 7c90e514 nt!KiFastCallEntry+0xf8
00abfd74 7c90d09a ntdll!KiFastSystemCallRet
00abfd78 7c80a78a ntdll!NtCreateEvent+0xc
00abfdc4 76d525a0 kernel32!CreateEventW+0x67
WARNING: Frame IP not in any known module. Following frames may be wrong.
00abfe68 7c917719 0x76d525a0
00abffa0 77de354b ntdll!LdrpGetProcedureAddress+0xa6
00abffbc 00000000 ADVAPI32!ScSvcctrlThreadA+0x12
А дальше казалось бы, логично проделать теже действия, что и WinDbg, и достать id из стаба ntdll, т.е. выполнить стек бектрейс, например, используя RtlCaptureStackBackTrace. И все бы хорошо, но данная ф-ция вернет лишь три верхних строчки из приведенного лога. И это понятно, т.к. ф-ция прыгает по цепочкам ebp фреймов, но допрыгать ф-ция может лишь до места, где копируется юзермодный стек в ядерный ( в обработчике sysenter ).
Где же взять информацию о юзермодном стеке? Ответ прост: в трап фрейме:
kd> dt nt!_KTRAP_FRAME 0xee6aed64
...
+0x070 EFlags : 0x202
+0x074 HardwareEsp : 0xabfd78 <========== юзермодный стек
+0x078 HardwareSegSs : 0x23
а вот и то, что нужно:
kd> dds 0xabfd78
00abfd78 7c90d09a ntdll!NtCreateEvent+0xc
00abfd7c 7c80a78a kernel32!CreateEventW+0x67
kd> u 7c90d09a
ntdll!NtCreateEvent+0xc:
7c90d09a c21400 ret 14h
7c90d09d 90 nop
Теперь можно прочитать id:
kd> u NtCreateEvent
ntdll!ZwCreateEvent:
7c90d08e b823000000 mov eax,23h <== id
7c90d093 ba0003fe7f mov edx,offset SharedUserData!SystemCallStub (7ffe0300)
7c90d098 ff12 call dword ptr [edx]
7c90d09a c21400 ret 14h
То есть, бектрейс в данном случае оказался совсем не нужным.
На х64 все еще проще, id сискола сохраняется в KTHREAD_SystemCallNumber(название по памяти пишу, могу ошибаться в имени поля).
Комментариев нет:
Отправить комментарий