l_sunny
Участник
Offline
|
|
« : 27-05-2010 17:02 » |
|
Если переменная - Id потока: DWORD idThread (параметр из NtUserSetWindowsHookEx), требуется узнать Pid процесса, которому принадлежит этот поток. Может кто знает?
|
|
|
Записан
|
|
|
|
Ochkarik
|
|
« Ответ #1 : 27-05-2010 21:54 » |
|
если это тот ThreadId, который PsLookupThreadByThreadIdа судя по реализации NtUserSetWindowsHookEx в ReactOS - это должна быть она... то с помощью PsLookupThreadByThreadId(или ObReferenceObjectByHandle) можно получить PETHREAD, первый параметр которой KTHREAD Tcb; одно из полей которого PKPROCESS Process; а вот PEPROCESS (в котором содержится PVOID UniqueProcessId -это то что вам нужно?) в нем уже нет... так что получается что перебором как на wasm... что ли... хотя это кривой способ.... но я не уверен, тот ли это ProcessId что вы хотели? PS думаю стоит еще поискать более "прямые" способы.... просто это - то что я поиском нагуглил) PPS ObReferenceObjectByHandle - посмотрите, я что то не понял с ходу что за структуру она вернет....
|
|
« Последнее редактирование: 27-05-2010 22:02 от Ochkarik »
|
Записан
|
RTFM уже хоть раз наконец! :[ ну или хотя бы STFW...
|
|
|
l_sunny
Участник
Offline
|
|
« Ответ #2 : 28-05-2010 05:56 » |
|
Спасибо за ответ. PsLookupThreadByThreadId как раз то что надо, но эта функция возвращает PETHREAD. Посмотрев исходники ReactOS, обнаружил, что в PETHREAD оказывается есть PEPROCESS. В этом объявлении структуры PETHREAD отсутствует PEPROCESS, а в ReactOS-0.3.11\include\ndk\pstypes.h есть. Написал небольшой примерчик, практически проверено только на WinXP SP3. typedef struct _ETHREAD_NEW { KTHREAD Tcb; LARGE_INTEGER liCreateTime; LARGE_INTEGER liExitTime; NTSTATUS ExitStatus; LIST_ENTRY PostBlockList; LIST_ENTRY TerminationPortList; ULONG uActiveTimerListLock; LIST_ENTRY ActiveTimerListHead; CLIENT_ID Cid; KSEMAPHORE LpcReplySemaphore; ULONG uLpcReplyMessage; LARGE_INTEGER liLpcReplyMessageId; ULONG uImpersonationInfo; LIST_ENTRY IrpList; LIST_ENTRY TopLevelIrp; PDEVICE_OBJECT DeviceToVerify; // from ReactOS-0.3.11\include\ndk\pstypes.h struct _EPROCESS *ThreadsProcess; // from ReactOS-0.3.11\include\ndk\pstypes.h // ... } ETHREAD_NEW, *PETHREAD_NEW;
NTSTATUS LookupProcessIdByThreadId(DWORD ThreadId, ULONG *ProcessId) { PETHREAD_NEW Thread; NTSTATUS status = PsLookupThreadByThreadId((HANDLE) ThreadId,(PETHREAD*)&Thread); if (NT_SUCCESS(status)) { PEPROCESS eprocess = Thread->ThreadsProcess; *ProcessId=(ULONG)eprocess->UniqueProcessId; ObDereferenceObject(Thread); } return status; }
|
|
|
Записан
|
|
|
|
resource
Молодой специалист
Offline
Пол:
|
|
« Ответ #3 : 28-05-2010 07:03 » |
|
Есть еще NtQueryInformationThread. Правда нужно сначала получить HANDLE потока.
|
|
|
Записан
|
|
|
|
Ochkarik
|
|
« Ответ #4 : 28-05-2010 18:11 » |
|
источник http://www.rsdn.ru/forum/asm/2113192.flat.aspxтам есть win-2003 win-xp w2k NT4. PS приатачиваю дамп PDB ntoskrnl от XP и 2K3 (слито оттуда же) и текстовую версию из форума RSDN в которой собственно эти структуры расписаны... вдруг чего понадобится?)
|
|
« Последнее редактирование: 28-05-2010 18:13 от Ochkarik »
|
Записан
|
RTFM уже хоть раз наконец! :[ ну или хотя бы STFW...
|
|
|
x64
|
|
« Ответ #5 : 28-05-2010 23:37 » |
|
Эти функции: NTSTATUS PsLookupProcessThreadByCid ( IN PCLIENT_ID Cid, OUT PEPROCESS* Process OPTIONAL, OUT PETHREAD* Thread);
HANDLE PsGetProcessId ( IN PEPROCESS Process);
|
|
|
Записан
|
|
|
|
Ochkarik
|
|
« Ответ #6 : 29-05-2010 08:51 » |
|
да, но к сожалению Cid все равно из PETHREAD выдирать придется... или тоже есть способ обойтись? и PsLookupProcessThreadByCid в msdn не объявлена... хотя использовать недокументированные функции, наверное, меньший грех, чем использовать недокументированные структуры))) ps кстати http://razzle.ath.cx:8080/ntosdropce/WIN_RELEASE/base/ntos/ps/pscid.c/*++
Copyright (c) Microsoft Corporation. All rights reserved.
You may only use this code if you agree to the terms of the Windows Research Kernel Source Code License agreement (see License.txt). If you do not agree to the terms, do not use the code.
Module Name:
pscid.c
Abstract:
This module implements the Client ID related services.
--*/
#include "psp.h"
#ifdef ALLOC_PRAGMA #pragma alloc_text(PAGE, PsLookupProcessThreadByCid) #pragma alloc_text(PAGE, PsLookupProcessByProcessId) #pragma alloc_text(PAGE, PsLookupThreadByThreadId) #endif //ALLOC_PRAGMA
NTSTATUS PsLookupProcessThreadByCid( __in PCLIENT_ID Cid, __deref_opt_out PEPROCESS *Process, __deref_out PETHREAD *Thread )
/*++
Routine Description:
This function accepts The Client ID of a thread, and returns a referenced pointer to the thread, and possibly a referenced pointer to the process.
Arguments:
Cid - Specifies the Client ID of the thread.
Process - If specified, returns a referenced pointer to the process specified in the Cid.
Thread - Returns a referenced pointer to the thread specified in the Cid.
Return Value:
STATUS_SUCCESS - A process and thread were located based on the contents of the Cid.
STATUS_INVALID_CID - The specified Cid is invalid.
--*/
{
PHANDLE_TABLE_ENTRY CidEntry; PETHREAD lThread; PETHREAD CurrentThread; PEPROCESS lProcess; NTSTATUS Status;
PAGED_CODE();
lThread = NULL;
CurrentThread = PsGetCurrentThread (); KeEnterCriticalRegionThread (&CurrentThread->Tcb);
CidEntry = ExMapHandleToPointer(PspCidTable, Cid->UniqueThread); if (CidEntry != NULL) { lThread = (PETHREAD)CidEntry->Object; if (!ObReferenceObjectSafe (lThread)) { lThread = NULL; } ExUnlockHandleTableEntry(PspCidTable, CidEntry); }
KeLeaveCriticalRegionThread (&CurrentThread->Tcb);
Status = STATUS_INVALID_CID; if (lThread != NULL) { // // This could be a thread or a process. Check its a thread. // if (lThread->Tcb.Header.Type != ThreadObject || lThread->Cid.UniqueProcess != Cid->UniqueProcess || lThread->GrantedAccess == 0) { ObDereferenceObject (lThread); } else { *Thread = lThread; if (ARGUMENT_PRESENT (Process)) { lProcess = THREAD_TO_PROCESS (lThread); *Process = lProcess; // // Since the thread holds a reference to the process this reference does not have to // be protected. // ObReferenceObject (lProcess); } Status = STATUS_SUCCESS; }
}
return Status; }
NTSTATUS PsLookupProcessByProcessId( __in HANDLE ProcessId, __deref_out PEPROCESS *Process )
/*++
Routine Description:
This function accepts the process id of a process and returns a referenced pointer to the process.
Arguments:
ProcessId - Specifies the Process ID of the process.
Process - Returns a referenced pointer to the process specified by the process id.
Return Value:
STATUS_SUCCESS - A process was located based on the contents of the process id.
STATUS_INVALID_PARAMETER - The process was not found.
--*/
{
PHANDLE_TABLE_ENTRY CidEntry; PEPROCESS lProcess; PETHREAD CurrentThread; NTSTATUS Status;
PAGED_CODE();
Status = STATUS_INVALID_PARAMETER;
CurrentThread = PsGetCurrentThread (); KeEnterCriticalRegionThread (&CurrentThread->Tcb);
CidEntry = ExMapHandleToPointer(PspCidTable, ProcessId); if (CidEntry != NULL) { lProcess = (PEPROCESS)CidEntry->Object; if (lProcess->Pcb.Header.Type == ProcessObject && lProcess->GrantedAccess != 0) { if (ObReferenceObjectSafe(lProcess)) { *Process = lProcess; Status = STATUS_SUCCESS; } }
ExUnlockHandleTableEntry(PspCidTable, CidEntry); }
KeLeaveCriticalRegionThread (&CurrentThread->Tcb); return Status; }
NTSTATUS PsLookupThreadByThreadId( __in HANDLE ThreadId, __deref_out PETHREAD *Thread )
/*++
Routine Description:
This function accepts the thread id of a thread and returns a referenced pointer to the thread.
Arguments:
ThreadId - Specifies the Thread ID of the thread.
Thread - Returns a referenced pointer to the thread specified by the thread id.
Return Value:
STATUS_SUCCESS - A thread was located based on the contents of the thread id.
STATUS_INVALID_PARAMETER - The thread was not found.
--*/
{
PHANDLE_TABLE_ENTRY CidEntry; PETHREAD lThread; PETHREAD CurrentThread; NTSTATUS Status;
PAGED_CODE();
Status = STATUS_INVALID_PARAMETER;
CurrentThread = PsGetCurrentThread (); KeEnterCriticalRegionThread (&CurrentThread->Tcb);
CidEntry = ExMapHandleToPointer(PspCidTable, ThreadId); if (CidEntry != NULL) { lThread = (PETHREAD)CidEntry->Object; if (lThread->Tcb.Header.Type == ThreadObject && lThread->GrantedAccess) {
if (ObReferenceObjectSafe(lThread)) { *Thread = lThread; Status = STATUS_SUCCESS; } }
ExUnlockHandleTableEntry(PspCidTable, CidEntry); }
KeLeaveCriticalRegionThread (&CurrentThread->Tcb);
return Status; }
|
|
« Последнее редактирование: 29-05-2010 09:25 от Ochkarik »
|
Записан
|
RTFM уже хоть раз наконец! :[ ну или хотя бы STFW...
|
|
|
x64
|
|
« Ответ #7 : 29-05-2010 17:27 » |
|
да, но к сожалению Cid все равно из PETHREAD выдирать придется... Весь Cid не нужен, только ID потока, который у автора уже есть (параметр функции). использовать недокументированные функции, наверное, меньший грех, чем использовать недокументированные структуры Да.
|
|
|
Записан
|
|
|
|
resource
Молодой специалист
Offline
Пол:
|
|
« Ответ #8 : 29-05-2010 17:37 » |
|
задача только какая-то не практическая чтоли. когда получаешь id потока, почему бы сразу не получить id процесса, и все эти манипуляции будут излишними.
|
|
|
Записан
|
|
|
|
Ochkarik
|
|
« Ответ #9 : 29-05-2010 20:08 » |
|
x64, вы предлагаете самому заполнить Cid->UniqueThread? так ведь PCLIENT_ID - тоже недокументирована...правда она совсем простая typedef struct _CLIENT_ID { HANDLE UniqueProcess; HANDLE UniqueThread; } CLIENT_ID, *PCLIENT_ID; но нужно еще выполнить условие: (lThread->Cid.UniqueProcess == Cid->UniqueProcess), в противном случае PsLookupProcessThreadByCid вернет STATUS_INVALID_CID судя по приведенной выше реализации. resource, мало ли... случаи разные бывают)
|
|
« Последнее редактирование: 29-05-2010 20:14 от Ochkarik »
|
Записан
|
RTFM уже хоть раз наконец! :[ ну или хотя бы STFW...
|
|
|
resource
Молодой специалист
Offline
Пол:
|
|
« Ответ #10 : 29-05-2010 22:19 » |
|
Ochkarik, Уж не буду вопрошать "например?". Пусть это останется на совести ТС.
|
|
|
Записан
|
|
|
|
x64
|
|
« Ответ #11 : 30-05-2010 06:23 » |
|
но нужно еще выполнить условие: (lThread->Cid.UniqueProcess == Cid->UniqueProcess), в противном случае PsLookupProcessThreadByCid вернет STATUS_INVALID_CID... Да, совершенно верно, я ошибся, гораздо проще будет так: NTSTATUS PsLookupThreadByThreadId ( IN HANDLE ThreadId, OUT PETHREAD* Thread);
PEPROCESS IoThreadToProcess ( IN PETHREAD Thread);
HANDLE PsGetProcessId ( IN PEPROCESS Process);
|
|
|
Записан
|
|
|
|
resource
Молодой специалист
Offline
Пол:
|
|
« Ответ #12 : 30-05-2010 07:30 » |
|
А вот это отличный вариант. Полностью документированный
|
|
|
Записан
|
|
|
|
Ochkarik
|
|
« Ответ #13 : 30-05-2010 07:50 » |
|
) ...вот ведь распихали нужные функции по разным разделам)))))
|
|
|
Записан
|
RTFM уже хоть раз наконец! :[ ну или хотя бы STFW...
|
|
|
resource
Молодой специалист
Offline
Пол:
|
|
« Ответ #14 : 30-05-2010 15:46 » |
|
Ochkarik, и не говори
|
|
|
Записан
|
|
|
|
l_sunny
Участник
Offline
|
|
« Ответ #15 : 01-06-2010 09:48 » |
|
задача только какая-то не практическая чтоли. когда получаешь id потока, почему бы сразу не получить id процесса, и все эти манипуляции будут излишними.
Перехватываю NtUserSetWindowsHookEx и нужно узнать какой процесс пытается поставить хук, а известно только id потока.
|
|
|
Записан
|
|
|
|
l_sunny
Участник
Offline
|
|
« Ответ #16 : 01-06-2010 09:50 » |
|
Большое спасибо за "правильный" способ, а то использовать недокументированные структуры как-то не хочется.
|
|
|
Записан
|
|
|
|
resource
Молодой специалист
Offline
Пол:
|
|
« Ответ #17 : 01-06-2010 10:00 » |
|
А как перехват осуществляется? Через SSDT ? Хотя собственно какая разница, все равно можно сразу получить ID процесса тут же при перехвате.
|
|
|
Записан
|
|
|
|
l_sunny
Участник
Offline
|
|
« Ответ #18 : 02-06-2010 10:20 » |
|
Да, указатель на NtUserSetWindowsHookEx подменял в KeServiceDescriptorTableShadow, а то в KeServiceDescriptorTable GDI-шные функции отсутствуют.
|
|
|
Записан
|
|
|
|
|