Не могу определить имя процесса по PID при его закрытии
От: ScorpeeOn  
Дата: 16.11.07 20:27
Оценка:
Привет Всем!
Помогите плз разобраться с проблемой. Тут драйвер пробую написать для отслеживания запуска и завершения процессов (PsSetCreateProcessNotifyRoutine) и хочу получать имена исполняемых модулей. При запуске все хорошо и имя процесса я могу увидеть, но вот при завершении имя процесса не могу получить (пустая строка получается). Вот код функции, в которой получаю имя по PID:

NTSTATUS GetProcessNameByPID(IN HANDLE ProcessId, OUT PCHAR ProcessName) {

    ULONG ulBufferSize = 0x8000;
    LPVOID pBuffer = NULL;
    NTSTATUS Status;
    PSYSTEM_PROCESSES pSystemProcessInfo;
    ULONG tmp;

    do
    {
        pBuffer = ExAllocatePool (NonPagedPool, ulBufferSize);
        if( pBuffer == NULL ) {
            return STATUS_UNSUCCESSFUL;
        }
        
        Status = ZwQuerySystemInformation(SystemProcessesAndThreadsInformation, 
                                          pBuffer, ulBufferSize, NULL);
        
        if( Status == STATUS_INFO_LENGTH_MISMATCH ) {
            ExFreePool(pBuffer); 
            ulBufferSize *= 2;
        }
        else if( !NT_SUCCESS(Status) ) {
            ExFreePool(pBuffer);
            return STATUS_UNSUCCESSFUL;
        }

    }
    while (Status == STATUS_INFO_LENGTH_MISMATCH);

    pSystemProcessInfo = (PSYSTEM_PROCESSES)pBuffer;

    for(;;) {

        LPWSTR pszProcessName = pSystemProcessInfo->ProcessName.Buffer;
        
        if( pszProcessName == NULL ) {
            pszProcessName = L"Idle";
        }

        if( pSystemProcessInfo->ProcessId == (ULONG)ProcessId ) { 
            tmp = wcstombs(ProcessName, pszProcessName, PROCNAMELEN);
            break;
        }

        if( pSystemProcessInfo->NextEntryDelta == 0 ) {
            break;
        }

        pSystemProcessInfo = (PSYSTEM_PROCESSES)(((PUCHAR)pSystemProcessInfo)+pSystemProcessInfo->NextEntryDelta);

    }
    
    DbgPrint("Process name: %s %lu", ProcessName, tmp); // Вот тут не вижу процесса при его завершении, а tmp равна какому-то большому числу.

    ExFreePool(pBuffer);
    return STATUS_SUCCESS;

}


В чем может быть причина? Помогите плиз...
С уважением,
Евгений
Re: Не могу определить имя процесса по PID при его закрытии
От: Valery A. Boronin Россия linkedin.com/in/boronin
Дата: 16.11.07 20:33
Оценка: +1
Здравствуйте, ScorpeeOn, Вы писали:

SO>Помогите плз разобраться с проблемой. Тут драйвер пробую написать для отслеживания запуска и завершения процессов (PsSetCreateProcessNotifyRoutine) и хочу получать имена исполняемых модулей. При запуске все хорошо и имя процесса я могу увидеть, но вот при завершении имя процесса не могу получить (пустая строка получается). Вот код функции, в которой получаю имя по PID:

рассмотрите возможность сохранить имя процесса для дальнейшего использования, предварительно ассоциировав его с PID/PEPROCESS
... << RSDN@Home 1.2.0 alpha rev. 0>>
Valery A. Boronin, RSDN Team, linkedin.com\in\boronin
R&D Mgmt & Security. AppSec & SDL. Data Protection and Systems Programming. FDE, DLP, Incident Management. Windows Filesystems and Drivers.
Re[2]: Не могу определить имя процесса по PID при его закрыт
От: Unmanaged Россия ICQ 476611995
Дата: 16.11.07 21:59
Оценка: 4 (2)
SO>>Помогите плз разобраться с проблемой. Тут драйвер пробую написать для отслеживания запуска и завершения процессов (PsSetCreateProcessNotifyRoutine) и хочу получать имена исполняемых модулей. При запуске все хорошо и имя процесса я могу увидеть, но вот при завершении имя процесса не могу получить (пустая строка получается). Вот код функции, в которой получаю имя по PID:
VAB>рассмотрите возможность сохранить имя процесса для дальнейшего использования, предварительно ассоциировав его с PID/PEPROCESS

Imho, это самый грамотный способ и в коммерческом проекте я бы предпочёл именно его.
Однако существуют и другие способы:

1. Поиск процесса 1

Найти процесс через PsLookupProcessByProcessId() по его ID.
Имея объект процесса, действовать как в п.2.

К сожалению, этот способ работать не будет, т.к. функция PsLookupProcessByProcessId() на момент вызова колбэка будет считать, что процесса уже не существует.
Более подробное обсуждение здесь.

2. Поиск процесса 2

Существует список объектов EPROCESS.
Указатель на начало этого списка храниться в каждом объекте-процессе в структуре EPROCESS в поле ActiveProcessLinks:

typedef struct _EPROCESS
{
  ...
  LIST_ENTRY                      ActiveProcessLinks;
  ...
}
EPROCESS, *PEPROCESS;


Пробежавшись по списку, можно перечислить все процессы, глядя на ID каждого из них.

В случае совпадения открыть объект через ObOpenObjectByPointer().
Запросить полный путь к исполняемому файлу процесса через ZwQueryInformationProcess() с классом ProcessImageFileName или ProcessImageFileNameWin32 (начиная с Vista) на полученный хендл.

Проблема здесь будет в том, что структура EPROCESS недокументирована и различается в разных версиях Windows.
Тем не менее, объявления соответствующих структур можно без проблем найти в сети.

3. Открытие процесса

Открыть процесс через ZwOpenProcess() по ID процесса.
По возвращёному хендлу получить указатель на объект процесса через ObReferenceObjectByHandle().
Имея на руках объект процесса, получить по нему имя как описано в п.2.

Есть и другие способы, — преимущественно, грязнохаки с хардкодингами.
STATUS_INVALID_DEVICE_REQUEST
Re[3]: Не могу определить имя процесса по PID при его закрыт
От: ScorpeeOn  
Дата: 17.11.07 08:43
Оценка:
Здравствуйте, Unmanaged, Вы писали:

...

Спасибо за ответ.
Я пробовал делать так:

void GetProcessNameOffset()
{
    PEPROCESS curproc;
    int i;
    curproc = PsGetCurrentProcess();
    for( i = 0; i < 3*PAGE_SIZE; i++ )
    {
        if( !strncmp( "System", (PCHAR) curproc + i, strlen("System") ))
        {
            gProcessNameOffset = i;
        }
    }
}

NTSTATUS GetProcessNameById(OUT PCHAR ProcessName, IN HANDLE ProcessId)
{
    PEPROCESS       curproc;
    char            *nameptr;
    
    if (!gProcessNameOffset || !ProcessId) return STATUS_INVALID_PARAMETER;
    if (!NT_SUCCESS(PsLookupProcessByProcessId(ProcessId,&curproc))) 
        return STATUS_INVALID_PARAMETER;
    nameptr   = (PCHAR) curproc + gProcessNameOffset;
    strncpy( ProcessName, nameptr, PROCNAMELEN );
    ProcessName[PROCNAMELEN] = 0;
    return STATUS_SUCCESS;
}

получаю имена процессов и при старте и при закрытии. Но вот если имя процесса больше 16 символов, то оно обрезается. На wasm.ru получил такую информацию: "в eprocess ImageFileName это char[16] больше оно не умещает". Поэтому и решил через QuerySystemInformation c SystemProcessesAndThreadsInformation.

А можно про "сохранить имя процесса для дальнейшего использования, предварительно ассоциировав его с PID/PEPROCESS" по подробнее немного и если не сложно с кодом?

Заранее спасибо!
С уважением,
Евгений
Re[3]: Не могу определить имя процесса по PID при его закрыт
От: ScorpeeOn  
Дата: 17.11.07 21:49
Оценка:
Здравствуйте, Unmanaged, Вы писали:

U>2. Поиск процесса 2


U>Существует список объектов EPROCESS.

U>Указатель на начало этого списка храниться в каждом объекте-процессе в структуре EPROCESS в поле ActiveProcessLinks:

U>
U>typedef struct _EPROCESS
U>{
U>  ...
U>  LIST_ENTRY                      ActiveProcessLinks;
U>  ...
U>}
U>EPROCESS, *PEPROCESS;
U>


U>Пробежавшись по списку, можно перечислить все процессы, глядя на ID каждого из них.


U>В случае совпадения открыть объект через ObOpenObjectByPointer().

U>Запросить полный путь к исполняемому файлу процесса через ZwQueryInformationProcess() с классом ProcessImageFileName или ProcessImageFileNameWin32 (начиная с Vista) на полученный хендл.

Приветствую еще раз!

Функций ZwQueryInformationProcess и ObOpenObjectByPointer (Функция ObOpenObjectByPointer объявлена в Ntifs.h, который входит в состав IFSDK, поэтому определил сам) в ntddk.h нету. Я их сделал так в своем *.h:

NTSYSAPI NTSTATUS NTAPI
ZwQueryInformationProcess(
  IN       HANDLE ProcessHandle,
  IN       PROCESSINFOCLASS SystemInformationClass,
  OUT      PVOID SystemInformation,
  IN       ULONG SystemInformationLength,
  OUT      PULONG ReturnLength
);

NTSYSAPI NTSTATUS NTAPI
ObOpenObjectByPointer(
  IN PVOID  Object,
  IN ULONG  HandleAttributes,
  IN PACCESS_STATE  PassedAccessState OPTIONAL,
  IN ACCESS_MASK  DesiredAccess,
  IN POBJECT_TYPE  ObjectType,
  IN KPROCESSOR_MODE  AccessMode,
  OUT PHANDLE  Handle
);


пользуемся тагами ccode для обрамления кода на С\С++ — модератор

Можно ли так? Линкер не ругнулся.
Потом хочу получить имя как Вы и описывали, но получаю BSOD. В чем причина?
Без ObOpenObjectByPointer и ZwQueryInformationProcess работает и находит адрес EPROCESS по hProcID (причем при старте и завершении процесса адрес EPROCESS одинаковый, поэтому прально вроде все).
Вот код такой:

пользуемся тагами ccode для обрамления кода на С\С++ — модератор
// Для XP SP2
#define PIDOFFSET   0x84
#define FLINKOFFSET 0x88

...
while(1) {

    if( (DWORD)hProcID == dwCurrentPID ) {

        Status = ObOpenObjectByPointer((PVOID)hProcID,
                                       0,
                                       NULL,
                                       0,
                                       NULL,
                                       0,
                                       &hOutHandle);
        if(!NT_SUCCESS(Status)) {
            DbgPrint("Error: ObOpenObjectByPointer");
        }

        pBuffer = ExAllocatePool (NonPagedPool, ulBufferSize);
        if( pBuffer == NULL ) {
            return 0x00000000;
        }

        Status = ZwQueryInformationProcess(hOutHandle, SystemProcessImageFileName, 
                                  pBuffer, ulBufferSize, NULL);

        if( NT_SUCCESS(Status) ) {
            DbgPrint("YES");
        }

        ExFreePool(pBuffer);

        return ...;

    }
    else if( (dwCount >= 1) && (dwStartPID == dwCurrentPID) ) {
        return 0x00000000;
    }
    else {
        pListEntry = (LIST_ENTRY*)(dwEprocAddr+FLINKOFFSET);
        dwEprocAddr = (DWORD)pListEntry->Flink;
        dwEprocAddr = dwEprocAddr-FLINKOFFSET;
        dwCurrentPID = *((int*)(dwEprocAddr+PIDOFFSET));
        dwCount++;
    }
}
...
С уважением,
Евгений
Re[3]: Не могу определить имя процесса по PID при его закрыт
От: ScorpeeOn  
Дата: 18.11.07 10:25
Оценка:
Здравствуйте, Unmanaged, Вы писали:

U>2. Поиск процесса 2


U>Существует список объектов EPROCESS.

U>Указатель на начало этого списка храниться в каждом объекте-процессе в структуре EPROCESS в поле ActiveProcessLinks:

U>
U>typedef struct _EPROCESS
U>{
U>  ...
U>  LIST_ENTRY                      ActiveProcessLinks;
U>  ...
U>}
U>EPROCESS, *PEPROCESS;
U>


U>Пробежавшись по списку, можно перечислить все процессы, глядя на ID каждого из них.


U>В случае совпадения открыть объект через ObOpenObjectByPointer().

U>Запросить полный путь к исполняемому файлу процесса через ZwQueryInformationProcess() с классом ProcessImageFileName или ProcessImageFileNameWin32 (начиная с Vista) на полученный хендл.

Разобрался! Спасиб! +3
Только еще небольшой вопросик: у меня сейчас полный путь к процессу начинается с \Device\HarddiskVolume1\...путь_к _процессу...
Можно ли как-нить по привычнее, что-то типа C:\...путь_к _процессу... ?
С уважением,
Евгений
Re[4]: Не могу определить имя процесса по PID при его закрыт
От: Unmanaged Россия ICQ 476611995
Дата: 18.11.07 14:37
Оценка:
SO>Разобрался! Спасиб! +3

Совет на будущее: не торопитесь.
Вы знаете, народные мудрости, они ведь не на пустом месте придумывались...

SO>Только еще небольшой вопросик: у меня сейчас полный путь к процессу начинается с \Device\HarddiskVolume1\...путь_к _процессу...

SO>Можно ли как-нить по привычнее, что-то типа C:\...путь_к _процессу... ?

Очень не советую это делать.
Для Windows < Vista это связано с некоторым кол-вом проблем.

А вообще можно, конечно, если осторожно.
Итак, повторим.

1. Если Windows Vista и выше

ZwQueryInformationProcess() с флагом ProcessImageFileNameWin32.
Здесь больше ничего не нужно делать.

2. Если Windows Server 2003 и ниже

ZwQueryInformationProcess() с флагом ProcessImageFileName.

Дальше — держитесь крепче.
Для преобразования Native-имён я вижу 3 пути.
Рассмотрим их все по порядку.

2.1. Преобразование в User-Mode

Для этого в драйвере достаточно отдать имя как есть Native наверх приложению.
Как получить DOS-имя по Native в приложении показано здесь — Obtaining a File Name From a File Handle.
В данном примере функция GetMappedFileName() возвращает Native-имя, весь последующий код получает DOS-имя и выводит его.

2.2. Преобразование в Kernel-Mode, вариант 1

В драйвере отделить имя девайса \Device\HarddiskVolumeX от относительного имени файла \filename.ext.
На имя девайса натравить IoGetDeviceObjectPointer() — получаем указатель на VDOVolume Device Object.
На VDO натравить RtlVolumeDeviceToDosName() или IoVolumeDeviceToDosName() (для Windows XP и выше) — получаем DOS-имя девайса, например, C:.
Приклеить C: к \filename.ext — получаем DOS-имя C:\filename.ext.

2.3. Преобразование в Kernel-Mode, вариант 2

Здесь придётся рассказать немного теории.
Для начала скачайте программу WinObjEx (автор Андрей Ивлев aka Four-F) и запустите.

Смотрите влево, найдите папку GLOBAL?? — это объект, подконтрольный Менеджеру объектов Windows, — имеет тип Directory (папка).
Полное имя этой папки — \??, содержит объекты ядра, доступные пользовательским приложениям.
Ничего не замечаете знакомого?
Например, C:, D:, PRN, NUL, Tcp, LPT1, MAILSLOT и другие — всё это всего лишь символьные ссылки на действительные объекты ядра.
Нас интересуют как раз буквы логических дисков — Y:.
Полное имя каждой ссылки \??\Y:.

Угадайте, куда ведёт \??\Y: ?

  • Для гибких дисков — на \Device\FloppyX.
  • Для логических дисков на винте они ведут аккурат на \Device\HarddiskVolumeX.
  • Для компакт-дисков — на \Device\CdRomX.

    Всё это уже реальные объекты девайсов, конкретно — логических дисков.

    Таким образом, алгоритм в драйвере будет примерно таким:

    1. Отделить имя девайса \Device\HarddiskVolumeX от относительного имени файла \filename.ext.
    2. В цикле перебрать все символьные ссылки \??\Y: — c A по Z.
    3. Для каждой ссылки запросить её target (цель).
    См. функции ZwOpenSymbolicLinkObject() и ZwQuerySymbolicLinkObject().
    Например для \??\C: это скорее всего будет \Device\HarddiskVolume1.
    4. Если цель ссылки совпала с именем девайса, которое мы получили на шаге 1, тогда считаем, что Y: — это и есть DOS-имя нашего девайса.
    5. Теперь осталось приклеить полученное Y: к \filename.ext — имеем Y:\filename.ext.

    Если хорошо подумать, можно ещё придумать способы, но этих вам вполне хватит.
  • STATUS_INVALID_DEVICE_REQUEST
    Re[4]: Не могу определить имя процесса по PID при его закрыт
    От: Unmanaged Россия ICQ 476611995
    Дата: 18.11.07 14:53
    Оценка:
    SO>А можно про "сохранить имя процесса для дальнейшего использования, предварительно ассоциировав его с PID/PEPROCESS" по подробнее немного и если не сложно с кодом?

    Как я понимаю, вы уже решили проблему.
    Значит вам это уже не нужно.

    А вообще, имелось в виду следующее.

    Создаём список, используя либо свою реализацию, либо системную, например, см. Singly- and Doubly-Linked Lists.
    После получения имени при создании процесса, создаём экземпляр некой структуры, в которую записываем ID процесса и указатель на полученное имя.
    Указатель на эту структуру запихиваем с список.
    При уничтожении процесса берём из списка соответствующую структуру (ищем по ID процесса).
    Удаляем соответствующий элемент списка.
    Из структуры берём указатель на имя процесса.
    Уничтожаем структуру.
    Используем имя.
    Уничтожаем имя.

    Конец.
    STATUS_INVALID_DEVICE_REQUEST
    Re[5]: Не могу определить имя процесса по PID при его закрыт
    От: ScorpeeOn  
    Дата: 18.11.07 15:11
    Оценка:
    Здравствуйте, Unmanaged, Вы писали:
    ...

    Спасиб еще раз за помощь!
    Буду разбираться дальше.
    С уважением,
    Евгений
    Re[6]: Не могу определить имя процесса по PID при его закрыт
    От: Denwer Россия  
    Дата: 18.11.07 17:59
    Оценка: 5 (2)
    Здравствуйте, ScorpeeOn, Вы писали:

    SO>Здравствуйте, Unmanaged, Вы писали:

    SO>...

    SO>Спасиб еще раз за помощь!

    SO>Буду разбираться дальше.

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


            KeStackAttachProcess((PKPROCESS)pProcess, &ApcState);
    
        __try
        {
            PPEB pProcessPeb = pProcess->Peb;
            PRTL_USER_PROCESS_PARAMETERS pProcessParameters = pProcessPeb->ProcessParameters;
    
            RtlCopyUnicodeString(&usImagePathName, &pProcessParameters->ImagePathName);
            RtlCopyUnicodeString(&usCommandLine, &pProcessParameters->CommandLine);
        }
        __except(EXCEPTION_EXECUTE_HANDLER)
        {
        }
    
        KeUnstackDetachProcess(&ApcState);



    Только не забыть нужно, что usImagePathName & usCommandLine — должны быть выделены в контексте системного потока.
    Re[5]: Не могу определить имя процесса по PID при его закрыт
    От: Valery A. Boronin Россия linkedin.com/in/boronin
    Дата: 18.11.07 20:24
    Оценка: 9 (2)
    Здравствуйте, Unmanaged, Вы писали:

    <...excess quoted lines suppressed...>
    U>Таким образом, алгоритм в драйвере будет примерно таким:

    U>1. Отделить имя девайса \Device\HarddiskVolumeX от относительного имени файла \filename.ext.

    U>2. В цикле перебрать все символьные ссылки \??\Y: — c A по Z.
    U>3. Для каждой ссылки запросить её target (цель).
    U>См. функции ZwOpenSymbolicLinkObject() и ZwQuerySymbolicLinkObject().
    U>Например для \??\C: это скорее всего будет \Device\HarddiskVolume1.
    если уж на то пошло, стоит отметить что процедуру следует применить не один раз (как следует из текста выше) — а в цикле и до победного конца — ссылки на ссылки на ссылки и т.п. тоже встречаются и не так уж и редко. Впрочем детали можно найти в поиске — неоднократно сие решение публиковалось в этом и возможно в win api форуме для Native API.

    U>4. Если цель ссылки совпала с именем девайса, которое мы получили на шаге 1, тогда считаем, что Y: — это и есть DOS-имя нашего девайса.

    U>5. Теперь осталось приклеить полученное Y: к \filename.ext — имеем Y:\filename.ext.

    U>Если хорошо подумать, можно ещё придумать способы, но этих вам вполне хватит.

    а теперь еще раз смотрим на всю эту канитель и читаем то что было написано в моем первом сообщении
    Автор: Valery A. Boronin
    Дата: 16.11.07
    еще раз.

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

    Вот поэтому и не хотел писать, но придется: действительно, Unmanaged натурально прав с самой первой строки
    Автор: Unmanaged
    Дата: 17.11.07
    — нужно иметь серьезные причины прежде чем начинать засовывать такие вещи в реальный проект, который планируется к использованию на достаточно большом количестве машин. Автору топика, возможно, не следует безоглядно пытаться реализовать все что было ему адресовано — но изучить и понять несомненно имеет смысл.


    PS кстати коллеге Unmanaged хочу заметить что вести себя подобным образом — нет, не то чтобы недопустимо, просто выглядит весьма комично откровенно говоря... и даже несмотря на это и то, что Вы, очевидно, потратили время на набор своих сообщений, могущих кому-то оказаться полезными — что я отлично понимаю и действительно ценю — тем не менее ситуация вынуждает меня отделить эту ветку в мусорку ибо правила есть правила и едины для всех, извините.

    PPS Посему прошу впредь находить для развлечений какое-нибудь более подходящее место — это уже модератор с Вами разговаривает.
    ... << RSDN@Home 1.2.0 alpha rev. 0>>
    Valery A. Boronin, RSDN Team, linkedin.com\in\boronin
    R&D Mgmt & Security. AppSec & SDL. Data Protection and Systems Programming. FDE, DLP, Incident Management. Windows Filesystems and Drivers.
    Re[7]: Не могу определить имя процесса по PID при его закрыт
    От: TarasCo  
    Дата: 19.11.07 09:55
    Оценка: 1 (1)
    D>Я использую такой способ получения полного пути для процессов. Минусы знаю, можете не писать
    D>Единственное хочу сказать, работает на всех виндах у меня нормально.

    И как всегда помним, что подобные штуки применимы только к добропорядочным приложениям. Для борьбы с злонамеренными не подходит, поскольку в PEB е может быть написано все что угодно и кем угодно .
    Да пребудет с тобою сила
    Re[6]: Не могу определить имя процесса по PID при его закрыт
    От: Unmanaged Россия ICQ 476611995
    Дата: 19.11.07 14:24
    Оценка:
    VAB>если уж на то пошло, стоит отметить что процедуру следует применить не один раз (как следует из текста выше) — а в цикле и до победного конца — ссылки на ссылки на ссылки и т.п. тоже встречаются и не так уж и редко.

    Дайте же человеку подумать хоть немного самостоятельно!

    VAB>Сравниваем трудоемкость предложенных решений (почему-то уверен что мое бы автор топика реализовал минут за 20 ). Сравниваем надежность предложенных решений, сравниваем ветвления в зависимости от ОС и прочие осложняющие жизнь (в т.ч. и тестерам!) вещи, не говоря уже о производительности решения выше и поиска в своем ассоциативном кэше... вспоминаем о постановке задачи автором топика.


    Мне кажется что автор топика решил просто поиграться.
    Именно для подобных игр с кернелом мной и были предложены вышеописанные решения.

    А для серьёзных коммерческих продуктов вашего ответа, действительно, было вполне достаточно.

    VAB>Вот поэтому и не хотел писать, но придется: действительно, Unmanaged натурально прав с самой первой строки
    Автор: Unmanaged
    Дата: 17.11.07
    ...


    Пасиба.
    Я знаю .

    VAB>Автору топика, возможно, не следует безоглядно пытаться реализовать все что было ему адресовано — но изучить и понять несомненно имеет смысл.


    Согласен.

    VAB>...тем не менее ситуация вынуждает меня отделить эту ветку в мусорку ибо правила есть правила и едины для всех, извините.


    Извиняю.
    Я знал что будет именно так, и всё же я успел донести свою мысль до автора.
    Неправда ли, я хитёр?

    VAB>PPS Посему прошу впредь находить для развлечений какое-нибудь более подходящее место — это уже модератор с Вами разговаривает.


    Да.
    У меня только один вопрос.
    Почему все 3 последние ссылки в вашем сообщении ведут на одну и ту же страницу, а не на разные, в зависимости от контекста?
    STATUS_INVALID_DEVICE_REQUEST
    Re[6]: Не могу определить имя процесса по PID при его закрыт
    От: ScorpeeOn  
    Дата: 19.11.07 17:46
    Оценка:
    Здравствуйте, Valery A. Boronin, Вы писали:

    ...

    Приветствую! Спасиб за ответы!
    Дело в том, что в нулевое кольцо я только-только начал лазить. Как я понял очень много инфы недокументировано, в т.ч. и на данную тему. Поэтому приходится рыскать по форумам и искать какие-нить исходники и пытаться осознавая собрать некий рабочий вариант.
    Ваш вариант, как я понял уже, самый лучший из предложенных, но...
    Вроде PID процесса получить могу, EPROCESS — тоже... Но я прочитал, цитирую: "Имя процесса в структуре EPROCESS — это 16-байтный массив, обычно содержащий первые 16 байт имени исполняемого файла на диске". Имя-то я должен буду по Вашему методу оттуда взять. Или я не не совсем понял, что Вы имели ввиду? И потом LIST_ENTRY формировать?
    С уважением,
    Евгений
    Re[6]: Не могу определить имя процесса по PID при его закрыт
    От: ScorpeeOn  
    Дата: 19.11.07 17:50
    Оценка:
    к предыдущему...

    Т.е. я смогу получить только имя процесса максимальной длины 16 байт, а все что больше будет обрезаться. Или нет?
    С уважением,
    Евгений
    Re[7]: Не могу определить имя процесса по PID при его закрыт
    От: Valery A. Boronin Россия linkedin.com/in/boronin
    Дата: 19.11.07 18:23
    Оценка: 1 (1)
    Здравствуйте, ScorpeeOn, Вы писали:

    SO>Дело в том, что в нулевое кольцо я только-только начал лазить. Как я понял очень много инфы недокументировано, в т.ч. и на данную тему. Поэтому приходится рыскать по форумам и искать какие-нить исходники и пытаться осознавая собрать некий рабочий вариант.

    все документировано.

    В Вашем первом сообщении
    Автор: ScorpeeOn
    Дата: 16.11.07
    , цитирую:

    Тут драйвер пробую написать для отслеживания запуска и завершения процессов (PsSetCreateProcessNotifyRoutine) и хочу получать имена исполняемых модулей. При запуске все хорошо и имя процесса я могу увидеть

    Вы же сами написали что здесь проблемы нет? Поэтому и был соответствующий ответ.

    если что — еще есть PsSetLoadImageNotifyRoutine, где имя модуля (в т.ч. модуля, хостящего процесс) идет параметром — поиграйте с этой функцией? иногда это удобнее чем вытягивать имя разными способами.

    SO>Ваш вариант, как я понял уже, самый лучший из предложенных, но...

    SO>Вроде PID процесса получить могу, EPROCESS — тоже... Но я прочитал, цитирую: "Имя процесса в структуре EPROCESS — это 16-байтный массив, обычно содержащий первые 16 байт имени исполняемого файла на диске". Имя-то я должен буду по Вашему методу оттуда взять. Или я не не совсем понял, что Вы имели ввиду? И потом LIST_ENTRY формировать?
    я нигде не говорил так делать — Вы путаете меня с кем-то в ветке. Лазать в недокументированные структуры по таким поводам, когда есть много способов добиться того же легальными методами (спасибо Unmanaged и за ликбез по вопросу)... такого я не мог посоветовать точно.

    Имя Вам приходит в документированный callback PsSetLoadImageNotifyRoutine — получите его там с комфортом и сохраните в загашнике.
    ... << RSDN@Home 1.2.0 alpha rev. 0>>
    Valery A. Boronin, RSDN Team, linkedin.com\in\boronin
    R&D Mgmt & Security. AppSec & SDL. Data Protection and Systems Programming. FDE, DLP, Incident Management. Windows Filesystems and Drivers.
    Re[7]: Не могу определить имя процесса по PID при его закрыт
    От: Unmanaged Россия ICQ 476611995
    Дата: 19.11.07 18:58
    Оценка: 14 (1)
    SO>Дело в том, что в нулевое кольцо я только-только начал лазить. Как я понял очень много инфы недокументировано, в т.ч. и на данную тему. Поэтому приходится рыскать по форумам и искать какие-нить исходники и пытаться осознавая собрать некий рабочий вариант.

    Хм.
    Хм...
    "Собрать некий рабочий вариант" — да, разве что "некий" и получиться.
    Плохой метод изучения ядра.
    Прежде всего — документация.

    SO>Ваш вариант, как я понял уже, самый лучший из предложенных, но...


    Да.
    Только вариант Валерия относиться исключительно к получению имени в момент завершения процесса, а не к получению имени вообще.

    SO>Вроде PID процесса получить могу, EPROCESS — тоже...


    Да, можешь.

    SO>Но я прочитал, цитирую: "Имя процесса в структуре EPROCESS — это 16-байтный массив, обычно содержащий первые 16 байт имени исполняемого файла на диске".


    Я вообще не понимаю зачем умники из M$ сделали это долбанное поле в этой долбанной ни хрена не документированной струкруре!
    Какая от него польза, ну какая?
    Аж страшно становится, когда бродишь отладчиком и находишь такие вещи.

    Автору.
    Это поле тебе не нужно.
    По уму имя процесса нужно брать методом, который я описал здесь
    Автор: Unmanaged
    Дата: 18.11.07
    , цитирую:

    1. Если Windows Vista и выше

    ZwQueryInformationProcess() с флагом ProcessImageFileNameWin32.

    2. Если Windows Server 2003 и ниже

    ZwQueryInformationProcess() с флагом ProcessImageFileName.


    HANDLE процесса по его ID в момент создания можно получить через PsLookupProcessByProcessId() и ObOpenObjectByPointer().
    Преобразовывать в DOS-имя можно как я описал там же — см. метод 2.1. Преобразование в User-Mode, исходник см. ниже.
    И, конечно, не забываем про безопасность
    Автор: TarasCo
    Дата: 19.11.07
    , если это важно.

    SO>Имя-то я должен буду по Вашему методу оттуда взять.


    Сколько я не перечитывал сообщения Валерия, я так и не нашёл места, откуда ты мог бы сделать подобный вывод.

    SO>Или я не не совсем понял, что Вы имели ввиду?


    Именно.

    В последнем своём сообщении
    Автор: Valery A. Boronin
    Дата: 18.11.07
    Валерий лишь имел в виду, что получать DOS-имя в ядре — занятие не самое тривиальное и, в общем-то, абсолютно не нужное.
    Вот тебе код, как это делать в User-ModeGetDosFileName(), набросал только что.
    Пользуйтесь моей добротой.

    В первом же сообщении
    Автор: Valery A. Boronin
    Дата: 16.11.07
    Валерий намекал на это
    Автор: Unmanaged
    Дата: 18.11.07
    .
    STATUS_INVALID_DEVICE_REQUEST
    Re[8]: Не могу определить имя процесса по PID при его закрыт
    От: ScorpeeOn  
    Дата: 19.11.07 19:17
    Оценка:
    Здравствуйте, Unmanaged, Вы писали:

    ...

    Спасиб еще раз за помощь! Буду разбираться.
    С уважением,
    Евгений
    сделаем акцент: DOS-names in Kernel? That's ridiculous!
    От: Valery A. Boronin Россия linkedin.com/in/boronin
    Дата: 19.11.07 20:14
    Оценка: 1 (1)
    Здравствуйте, ScorpeeOn, Вы писали:

    Евгений, лучше используйте поменьше цитирования — у нас древовидная структура, прочитать можно легко, что было до.

    SO>Только еще небольшой вопросик: у меня сейчас полный путь к процессу начинается с \Device\HarddiskVolume1\...путь_к _процессу...

    SO>Можно ли как-нить по привычнее, что-то типа C:\...путь_к _процессу... ?
    можно и все уже написано — спасибо Unmanaged за помощь. На пересечении наших ответов Вы можете со всем потихоньку разобраться.


    Однако еще раз подчеркну пожалуй главную мысль, которая судя по всему недостаточно акцентированно была выражена: "привычные" DOS имена в ядре — это нонсенс. Закладываться на DOS имена и не в ядре уже часто веcьма чревато. Особенно когда начнете наворачивать дыры в безопасности, опираясь на какие-то DOS-имена или жестко прописанные имена процессов\пользователей. Имен у файла может быть много (или не быть вовсе, если не считать fileID/ObjectID за имена), зависеть они могут даже от реализации сетевых редиректоров и много еще чего. Имен у тома может быть много и так далее. Подсунуть Вам могут иной раз что угодно, как правильно заметили в ветке... Иногда просто одни и те же вещи по-разному пишутся на разных языках, как ни странно.

    Поймите, если людям проще опираться на имена — то компьютерам проще опираться на понятные им ID кроме того это элементарно быстрее и программируется тоже быстрее.

    В нашем случае с процессами у нас есть PEPROCESS и PID, а вот DOS имена лучше не тащить в ядро. Они разве что для целей удобства логгирования\отладки могут быть полезны. В большинстве других случаев это может означать лишь что в дизайне проблемы. И даже хорошо что MSFT так усложнило получение DOS-имен — еще меньше соблазна изобретать решения на такой базе.

    Ссылки по теме:
    Re[4]: Доступ к драйверу
    Автор: Valery A. Boronin
    Дата: 17.03.06

    Re: При перехвате IoCreateFile() всё виснет! Помогите!
    Автор: Valery A. Boronin
    Дата: 02.07.06

    Re: Получение символа диска по имени устройства
    Автор: Valery A. Boronin
    Дата: 11.06.06
    ... << RSDN@Home 1.2.0 alpha rev. 0>>
    Valery A. Boronin, RSDN Team, linkedin.com\in\boronin
    R&D Mgmt & Security. AppSec & SDL. Data Protection and Systems Programming. FDE, DLP, Incident Management. Windows Filesystems and Drivers.
    Re: сделаем акцент: DOS-names in Kernel? That's ridiculous!
    От: Unmanaged Россия ICQ 476611995
    Дата: 19.11.07 20:22
    Оценка:
    Здравствуйте, Valery A. Boronin, Вы писали:

    ...

    Золотые слова.
    Тем не менее просящему — подай, ибо так надо.
    STATUS_INVALID_DEVICE_REQUEST
    Re: сделаем акцент: DOS-names in Kernel? That's ridiculous!
    От: ScorpeeOn  
    Дата: 20.11.07 15:37
    Оценка:
    Здравствуйте, Valery A. Boronin, Вы писали:

    >В нашем случае с процессами у нас есть PEPROCESS и PID, а вот DOS имена лучше не тащить в ядро.


    Мне-то и нужно, впринципе, только имя процесса, а не его полный путь на диске. Но из-за того, как я уже писал, в EPROCESS само имя процесса имеет максимальную длину 16 байт, то имена процессов, содержащих более 16 байт, обрезаются. Я бы и рад не делать так, как получилось (полностью имя на диске), но иначе я никак не могу сообразить как из PEPROCESS + PID получить необрезанное имя процесса при его запуске и останова. Ну вот не понимаю...
    С уважением,
    Евгений
    Re[2]: сделаем акцент: DOS-names in Kernel? That's ridiculou
    От: Unmanaged Россия ICQ 476611995
    Дата: 20.11.07 15:47
    Оценка:
    SO>...я никак не могу сообразить как из PEPROCESS + PID получить необрезанное имя процесса при его запуске и останова. Ну вот не понимаю...

    А это, батенька, после всего написанного — уже клиника.
    Ибо, например, здесь
    Автор: Denwer
    Дата: 18.11.07
    .
    STATUS_INVALID_DEVICE_REQUEST
    Re[3]: сделаем акцент: DOS-names in Kernel? That's ridiculou
    От: ScorpeeOn  
    Дата: 20.11.07 15:55
    Оценка:
    Здравствуйте, Unmanaged, Вы писали:

    SO>>...я никак не могу сообразить как из PEPROCESS + PID получить необрезанное имя процесса при его запуске и останова. Ну вот не понимаю...


    U>А это, батенька, после всего написанного — уже клиника.

    U>Ибо, например, здесь
    Автор: Denwer
    Дата: 18.11.07
    .


    Этот метод, как я понял, не очень хороший.
    Ладно, я сам порыщу.
    Спасиб всем!
    С уважением,
    Евгений
    Re[4]: сделаем акцент: DOS-names in Kernel? That's ridiculou
    От: Unmanaged Россия ICQ 476611995
    Дата: 20.11.07 16:00
    Оценка:
    U>>Ибо, например, здесь
    Автор: Denwer
    Дата: 18.11.07
    .

    SO>Этот метод, как я понял, не очень хороший.

    Ключевое слово — "например".

    SO>Ладно, я сам порыщу.


    Давно пора.

    P.S.
    Я к тому, что писать что-то типа дескать "я не могу понять это и это..." после того, как тебе всё разжевали и в рот положили, — ну как-то даже странновато.
    STATUS_INVALID_DEVICE_REQUEST
    терпение и труд все перетрут
    От: Valery A. Boronin Россия linkedin.com/in/boronin
    Дата: 20.11.07 17:17
    Оценка:
    ScorpeeOn,
    постарайтесь не хвататься за все — а выбрать что-то одно и например реализовать получение имени на старте, одним из предложенных способов (хотя Вы писали что это у Вас работает).

    Если что-то не будет получаться — лучше выложите свой код (помним про таги ccode) ф-ии callback что Вы вешаете на создание процесса и Вам помогут быстрее. Главное не торопитесь и не начинайте кодировать без четкого плана. Сначала нужно понять что Вам написали и осознать что именно Вы хотите сделать. И как. А когда это будет понятно — спокойно реализовать, не отвлекаясь на возможные альтернативы. Материала в ветке Вам предоставили достаточно для этого.

    Получив что-то работающее, Вы сможете двигаться дальше — реализовать кэш имен как я и предложил. Соответственно потом заменить все места где нужно имя процесса на поиск в кэше по PID/PEPROCESS. И не забыть вычищать элементы структур при завершении процесса, т.к. PID и PEPROCESS потом могут быть переиспользованы ОС.

    Все получится, главное — терпение и внимательность, сложного ничего нет — просто нужно "набить руку".
    ... << RSDN@Home 1.2.0 alpha rev. 0>>
    Valery A. Boronin, RSDN Team, linkedin.com\in\boronin
    R&D Mgmt & Security. AppSec & SDL. Data Protection and Systems Programming. FDE, DLP, Incident Management. Windows Filesystems and Drivers.
     
    Подождите ...
    Wait...
    Пока на собственное сообщение не было ответов, его можно удалить.