Перехват TerminateProcess и получение информации от дескриптора, который он предоставляет

Если вы хотите предотвратить завершение процесса, один из способов — подключиться к TerminateProcess (или NtTerminateProcess). Если процесс завершается (например, из-за того, что вы закрыли его окно), дескриптор, предоставленный этим функциям, равен NULL, поэтому вы можете узнать, какой исполняемый файл завершается, используя GetCurrentProcess() и GetModuleFileNameEx(). Поскольку GetCurrentProcess() возвращает псевдодескриптор, вы можете получить к нему доступ без проблем.

Однако если один процесс завершает другой, предоставленный дескриптор не равен NULL. Он представляет завершение процесса. Проблема в том, что вы не можете получить информацию об этом процессе. Вы можете просто вернуть код с сообщением «отказано в доступе» вместо вызова оригинального [Nt]TerminateProcess(), но это одеяло не позволяет всем процессам завершать другие, что является плохой идеей.

Дескриптор должен представлять что-то действительное, иначе TerminateProcess не сможет сделать с ним ничего полезного, но я даже не могу вызвать для него GetProcessId(), я получаю ERROR_INVALID_HANDLE (или ERROR_ACCESS_DENIED). Я пробовал различные методы, которые я собрал из справки и из Интернета, включая получение привилегии отладки (успех) и DuplicateHandle() (та же ошибка) и ZwQueryInformationProcess() для получения идентификатора (STATUS_ACCESS_DENIED). Я даже не могу перечислить процессы, потому что они возвращают идентификаторы, а я не могу получить идентификатор, а OpenProcess() всегда возвращает новый дескриптор, поэтому я не могу сравнивать дескрипторы.

Я могу только предположить, что дескриптор имеет право PROCESS_TERMINATE и ничего больше. Я знаю, что Vista и более поздние версии имеют защищенные процессы благодаря управлению цифровыми правами, но я использую ProcessExplorer в качестве подопытного кролика, так что это определенно не мультимедийное приложение!

Кто-нибудь знает, как еще я мог бы получить какую-либо информацию о завершении процесса из этого дескриптора?


person JTeagle    schedule 07.11.2010    source источник


Ответы (1)


Это просто обычный дескриптор процесса. Вопрос в том, в каком процессе выполняется ваша функция ловушки? Если это вызывающий процесс, дескриптор можно использовать как есть для GetProcessId или NtQueryInformationProcess. Если нет, вам нужно вызвать DuplicateHandle, чтобы дублировать дескриптор в ваш процесс.

Если вы получаете ошибки отказа в доступе, это может быть связано с тем, что дескриптор процесса имеет доступ только PROCESS_TERMINATE. В этом случае используйте DuplicateHandle, чтобы «повторно открыть» процесс с доступом PROCESS_QUERY_(LIMITED_)INFORMATION.

person wj32    schedule 07.11.2010
comment
Я упомянул в вопросе, что уже пробовал DuplicateHandle() (чтобы попытаться получить достаточный доступ), но безрезультатно. Поскольку хук внедряется в каждый процесс и может перехватывать только те вызовы, которые тот же процесс делает с NTDLL, его следует вызывать только в контексте завершающего приложения. Например, если ProcessExplorer завершает работу приложения, срабатывает код ловушки, отображенный в ProcessExplorer, и вы не согласны с тем, что тогда это должен быть собственный контекст ProcessExplorer? Это не может быть целевое приложение, так как оно не вызывало TerminateProcess... - person JTeagle; 08.11.2010
comment
Я должен уточнить, что я использую метод перехвата AppInit_DLLs, а не общесистемный перехватчик. Я забыл уточнить, что мой код хука выполняется только в приложении, вызывающем вызов для завершения другого. - person JTeagle; 08.11.2010
comment
Причина, по которой я упомянул об дескрипторах, заключалась в том, что вы не указали, как выполняется перехват, и упомянули о получении недопустимых ошибок дескрипторов. В чем именно проблема с использованием DuplicateHandle? Может быть, вы могли бы опубликовать код... - person wj32; 08.11.2010