Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: Как получить Pid процесса по ID потока  (Прочитано 21270 раз)
0 Пользователей и 3 Гостей смотрят эту тему.
l_sunny
Участник

ru
Offline Offline

« : 27-05-2010 17:02 » 

Если переменная - Id потока: DWORD idThread (параметр из NtUserSetWindowsHookEx),
требуется узнать Pid процесса, которому принадлежит этот поток.
Может кто знает?
Записан
Ochkarik
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #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 уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
l_sunny
Участник

ru
Offline 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
Молодой специалист

ru
Offline Offline
Пол: Мужской

« Ответ #3 : 28-05-2010 07:03 » 

Есть еще NtQueryInformationThread. Правда нужно сначала получить HANDLE потока.
Записан
Ochkarik
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #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 в которой собственно эти структуры расписаны... вдруг чего понадобится?)

* Структуры ядра - Низкоуровневое программирование - RSDN.htm (118.42 Кб - загружено 1852 раз.)
* ntkrnl.h.rar (219.11 Кб - загружено 1085 раз.)
« Последнее редактирование: 28-05-2010 18:13 от Ochkarik » Записан

RTFM уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
x64
Участник

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #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
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #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 уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
x64
Участник

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #7 : 29-05-2010 17:27 » 

Цитата
да, но к сожалению Cid все равно из PETHREAD выдирать придется...

Весь Cid не нужен, только ID потока, который у автора уже есть (параметр функции).

Цитата
использовать недокументированные функции, наверное, меньший грех, чем использовать недокументированные структуры

Да.
Записан
resource
Молодой специалист

ru
Offline Offline
Пол: Мужской

« Ответ #8 : 29-05-2010 17:37 » 

задача только какая-то не практическая чтоли. когда получаешь id потока, почему бы сразу не получить id процесса, и все эти манипуляции будут излишними.
Записан
Ochkarik
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #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 уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
resource
Молодой специалист

ru
Offline Offline
Пол: Мужской

« Ответ #10 : 29-05-2010 22:19 » 

Ochkarik,   Отлично Уж не буду вопрошать "например?". Пусть это останется на совести ТС.
Записан
x64
Участник

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #11 : 30-05-2010 06:23 » new

но нужно еще выполнить условие:
(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
Молодой специалист

ru
Offline Offline
Пол: Мужской

« Ответ #12 : 30-05-2010 07:30 » 

А вот это отличный вариант. Полностью документированный
Записан
Ochkarik
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #13 : 30-05-2010 07:50 » 

 Улыбаюсь)

...вот ведь распихали нужные функции по разным разделам)))))
Записан

RTFM уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
resource
Молодой специалист

ru
Offline Offline
Пол: Мужской

« Ответ #14 : 30-05-2010 15:46 » 

Ochkarik,  и не говори Класс!
Записан
l_sunny
Участник

ru
Offline Offline

« Ответ #15 : 01-06-2010 09:48 » 

задача только какая-то не практическая чтоли. когда получаешь id потока, почему бы сразу не получить id процесса, и все эти манипуляции будут излишними.
Перехватываю NtUserSetWindowsHookEx и нужно узнать какой процесс пытается поставить хук, а известно только id потока.
Записан
l_sunny
Участник

ru
Offline Offline

« Ответ #16 : 01-06-2010 09:50 » 

Большое спасибо за "правильный" способ, а то использовать недокументированные структуры как-то не хочется.
Записан
resource
Молодой специалист

ru
Offline Offline
Пол: Мужской

« Ответ #17 : 01-06-2010 10:00 » 

А как перехват осуществляется? Через SSDT ? Хотя собственно какая разница, все равно можно сразу получить ID процесса тут же при перехвате.
Записан
l_sunny
Участник

ru
Offline Offline

« Ответ #18 : 02-06-2010 10:20 » 

Да, указатель на NtUserSetWindowsHookEx подменял в KeServiceDescriptorTableShadow, а то в KeServiceDescriptorTable GDI-шные функции отсутствуют.
Записан
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines