Window station of a process
От: rus blood Россия  
Дата: 05.09.08 05:45
Оценка:
Есть хендл процесса.

Как определить, к какой window station он присоединен в данный момент?
Имею скафандр — готов путешествовать!
Re: Window station of a process
От: x64 Россия http://x64blog.name
Дата: 05.09.08 06:10
Оценка: 6 (1)
RB>Есть хендл процесса.
RB>Как определить, к какой window station он присоединен в данный момент?

VirtualAllocEx() + WriteProcessMemory() + CreateRemoteThread() + GetProcessWindowStation() + ReadProcessMemory(). Идея понятна? У хендла должны быть права PROCESS_CREATE_THREAD, PROCESS_QUERY_INFORMATION, PROCESS_VM_OPERATION, PROCESS_VM_WRITE и PROCESS_VM_READ. Единственный минус — не сработает для процесса в другом сеансе.
JID: x64j@jabber.ru
Re[2]: Window station of a process
От: rus blood Россия  
Дата: 05.09.08 06:24
Оценка:
Здравствуйте, x64, Вы писали:

x64>VirtualAllocEx() + WriteProcessMemory() + CreateRemoteThread() + GetProcessWindowStation() + ReadProcessMemory(). Идея понятна? У хендла должны быть права PROCESS_CREATE_THREAD, PROCESS_QUERY_INFORMATION, PROCESS_VM_OPERATION, PROCESS_VM_WRITE и PROCESS_VM_READ. Единственный минус — не сработает для процесса в другом сеансе.


Это слишком просто. В моем случае процесс мой, более того, есть открытый канал IPC к нему, так что передать инфу из процесса не составляет труда.

Меня интересует, не пропустил ли я что в API...
Имею скафандр — готов путешествовать!
Re: Window station of a process
От: rus blood Россия  
Дата: 05.09.08 06:31
Оценка:
Здравствуйте, rus blood, Вы писали:

А если есть хендл на десктоп, как определить, в какой window station он создан?
Имею скафандр — готов путешествовать!
Re[3]: Window station of a process
От: x64 Россия http://x64blog.name
Дата: 05.09.08 06:38
Оценка: -1
RB>В моем случае процесс мой, более того, есть открытый канал IPC к нему, так что передать инфу из процесса не составляет труда.

Мсье! Не вводите народ в заблуждение и внимательнее читайте документацию. GetProcessWindowStation() во втором процессе и переслать по IPC первому. Всё просто.
JID: x64j@jabber.ru
Re[2]: Window station of a process
От: x64 Россия http://x64blog.name
Дата: 05.09.08 06:42
Оценка:
RB>А если есть хендл на десктоп, как определить, в какой window station он создан?

EnumDesktops() + GetUserObjectInformation(UOI_NAME) + сравниваем имена. Идея понятна?
JID: x64j@jabber.ru
Re[3]: Window station of a process
От: rus blood Россия  
Дата: 05.09.08 06:56
Оценка:
Здравствуйте, x64, Вы писали:

RB>>А если есть хендл на десктоп, как определить, в какой window station он создан?


x64>EnumDesktops() + GetUserObjectInformation(UOI_NAME) + сравниваем имена. Идея понятна?


1. EnumDesktops дает имена десктопов, так что GetUserObjectInformation не требуется.
2. Допустим, мой десктоп называется "default". Еще идеи есть?
Имею скафандр — готов путешествовать!
Re[4]: Window station of a process
От: x64 Россия http://x64blog.name
Дата: 05.09.08 07:07
Оценка:
RB>GetUserObjectInformation не требуется.

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

RB>Допустим, мой десктоп называется "default".


Это к чему сказано было?

RB>Еще идеи есть?


Нет.
JID: x64j@jabber.ru
Re[5]: Window station of a process
От: rus blood Россия  
Дата: 05.09.08 08:55
Оценка:
Здравствуйте, x64, Вы писали:

x64>Да ну, правда? А как ты узнаешь имя собственного рабочего стола?


В этом смысле... Ну да, есть хендл на десктоп, и соответственно, все его атрибуты.


RB>>Допустим, мой десктоп называется "default".

x64>Это к чему сказано было?

К тому, что имена десктопов не уникальны. В разных window stations могут быть десктопы с одинаковым именем. Соответственно, исходный вопрос, как по десктопу найти его window station, остался открытым.


RB>>Еще идеи есть?

x64>Нет.

Плохо...
Имею скафандр — готов путешествовать!
Re[6]: Window station of a process
От: x64 Россия http://x64blog.name
Дата: 05.09.08 09:18
Оценка:
RB>К тому, что имена десктопов не уникальны. В разных window stations могут быть десктопы с одинаковым именем.

Эх, молодёжь. Что-то сегодня много народу в танк засели и вылазить ну решительно не хотят
Повторяю на раз: имена рабочих столов уникальны. Просто нужно немного подумать и придти к выводу, что имя рабочего стола это не "default", а "WinSta0\Default", ага.
JID: x64j@jabber.ru
Re[7]: Window station of a process
От: rus blood Россия  
Дата: 05.09.08 09:38
Оценка:
Здравствуйте, x64, Вы писали:

x64>Эх, молодёжь. Что-то сегодня много народу в танк засели и вылазить ну решительно не хотят


А-а-а... Ну ок, давай в такой плоскости ...

x64>Повторяю на раз: имена рабочих столов уникальны. Просто нужно немного подумать и придти к выводу, что имя рабочего стола это не "default", а "WinSta0\Default", ага.


Имя короткое, имя длинное, ага...

А не соизволит ли уважаемый джин вылезти из своей бутылки и продемонстрировать фокус с получением полного имени десктопа, включающего имя его window station, по имеющемуся хендлу HDESK ?
Имею скафандр — готов путешествовать!
Re[8]: Window station of a process
От: x64 Россия http://x64blog.name
Дата: 05.09.08 10:54
Оценка: -1 :)
RB>А не соизволит ли уважаемый джин вылезти из своей бутылки и продемонстрировать фокус с получением полного имени десктопа, включающего имя его window station, по имеющемуся хендлу HDESK ?

Ну что, готов, пионер? Пишем драйвер. Алгоритм будет примерно следующий:

1. В драйвер передаём хендл рабочего стола. Если кто ещё не знает, — это такой же хендл на объект ядра, как и все прочие нормальные хендлы.
2. Получаем указатель на объект рабочего стола через ObReferenceObjectByHandle(). Структура объекта рабочего стола чуть ниже.
3. Ищем в структуре поле rpwinstaParent (четвёртое сверху) и получаем указатель на объект родительской оконной станции.
4. Открываем объект оконной станции через ObOpenObjectByPointer(). Нам даже не нужно знать структуру её объекта, достаточно указателя.
5. Полученный хендл передаём наверх приложению и делаем с ним что хотим, можно, например, GetUserObjectInformation() позвать.

/*
 * Desktop Structure.
 *
 *   This structure is only viewable from the kernel.  If any desktop
 *   information is needed in the client, then they should reference off
 *   the pDeskInfo field (i.e. pti->pDeskInfo).
 */
typedef struct tagDESKTOP
{

    PDESKTOPINFO            pDeskInfo;         // Desktop information
    PDISPLAYINFO            pDispInfo;         //

    PDESKTOP                 rpdeskNext;       // Next desktop in list
    PWINDOWSTATION           rpwinstaParent;   // Windowstation owner

    DWORD                   dwDTFlags;         // Desktop flags
    ULONG                   dwDesktopId;       // Needed by GDI to tag display devices

    PWND                     spwndMenu;        //
    PMENU                    spmenuSys;        //
    PMENU                    spmenuDialogSys;  //
    PMENU                    spmenuHScroll;
    PMENU                    spmenuVScroll;
    PWND                     spwndForeground;  //
    PWND                     spwndTray;
    PWND                     spwndMessage;
    PWND                     spwndTooltip;

    HANDLE                  hsectionDesktop;   //
    PWIN32HEAP              pheapDesktop;      //
    DWORD                   dwConsoleThreadId; //
    DWORD                   dwConsoleIMEThreadId;
    CONSOLE_CARET_INFO      cciConsole;
    LIST_ENTRY              PtiList;           //

    PWND                    spwndTrack;        // xxxTrackMouseMove data
    int                     htEx;
    RECT                    rcMouseHover;
    DWORD                   dwMouseHoverTime;

    DWORD                   dwSessionId;

#ifdef LOGDESKTOPLOCKS
    int                     nLockCount;
    int                     nLogMax;
    int                     nLogCrt;
    PLogD                   pLog;
#endif // LOGDESKTOPLOCKS

}
DESKTOP;


Замечание. Приведённая структура может немного отличаться в современных версиях Windows. Проверять сей факт сейчас лень, но если очень попросите, я это сделаю, и даже драйверок накатать могу. Стучите в icq. А нормальными "легальными" способами сия проблема, насколько мне известно, не решается.

P.S. Функция NtQueryObject() возвращает имя в коротком формате "\<Object Name>", так что для решения нашей задачи не подходит.
JID: x64j@jabber.ru
Re[9]: Window station of a process
От: IID Россия  
Дата: 05.09.08 11:11
Оценка:
Здравствуйте, x64, Вы писали:

x64>Ну что, готов, пионер? Пишем драйвер. Алгоритм будет примерно следующий:


Отвратительно! Драйвер, лазанье по недокументированным структурам...
kalsarikännit
Re[10]: Window station of a process
От: x64 Россия http://x64blog.name
Дата: 05.09.08 11:49
Оценка:
IID>Отвратительно! Драйвер, лазанье по недокументированным структурам...

Мсье! Ну что вы как самый распоследний студент с WASM'а себя ведёте? Предложите вариант получше, а уж потом обхаивайте сколько душе угодно.
JID: x64j@jabber.ru
Re[9]: Window station of a process
От: rus blood Россия  
Дата: 06.09.08 10:01
Оценка:
Здравствуйте, x64, Вы писали:

x64>Ну что, готов, пионер?


Всегда!
Но с шашкой на танк — только после вас...

x64>Пишем драйвер.


x64>А нормальными "легальными" способами сия проблема, насколько мне известно, не решается.


Ну вот, а то enum desktops, get user information, имена какие-то...
Мне только этот факт и нужен был...
Имею скафандр — готов путешествовать!
Re: Window station of a process
От: xmen  
Дата: 07.09.08 19:37
Оценка: 6 (1)
Здравствуйте, rus blood, Вы писали:

RB>Есть хендл процесса.


RB>Как определить, к какой window station он присоединен в данный момент?



Вот написал, может, подойдет:

#pragma comment(linker, "-subsystem:windows")
#pragma comment(linker, "-entry:main")
#pragma comment(lib, "user32")

#define UNICODE
#include <windows.h>

typedef struct _UNICODE_STRING {
  USHORT Length;        /* bytes */
  USHORT MaximumLength; /* bytes */
  PWSTR  Buffer;
} UNICODE_STRING, *PUNICODE_STRING;

typedef struct _CURDIR
{
    UNICODE_STRING DosPath;
    PVOID Handle;
} CURDIR, *PCURDIR;

typedef struct RTL_DRIVE_LETTER_CURDIR
{
    USHORT              Flags;
    USHORT              Length;
    ULONG               TimeStamp;
    UNICODE_STRING      DosPath;
} RTL_DRIVE_LETTER_CURDIR, *PRTL_DRIVE_LETTER_CURDIR;

typedef struct _RTL_USER_PROCESS_PARAMETERS
{
    ULONG               AllocationSize;
    ULONG               Size;
    ULONG               Flags;
    ULONG               DebugFlags;
    HANDLE              ConsoleHandle;
    ULONG               ConsoleFlags;
    HANDLE              hStdInput;
    HANDLE              hStdOutput;
    HANDLE              hStdError;
    CURDIR              CurrentDirectory;
    UNICODE_STRING      DllPath;
    UNICODE_STRING      ImagePathName;
    UNICODE_STRING      CommandLine;
    PWSTR               Environment;
    ULONG               dwX;
    ULONG               dwY;
    ULONG               dwXSize;
    ULONG               dwYSize;
    ULONG               dwXCountChars;
    ULONG               dwYCountChars;
    ULONG               dwFillAttribute;
    ULONG               dwFlags;
    ULONG               wShowWindow;
    UNICODE_STRING      WindowTitle;
    UNICODE_STRING      Desktop;
    UNICODE_STRING      ShellInfo;
    UNICODE_STRING      RuntimeInfo;
    RTL_DRIVE_LETTER_CURDIR DLCurrentDirectory[0x20];
} RTL_USER_PROCESS_PARAMETERS, *PRTL_USER_PROCESS_PARAMETERS;

main()
{
    PRTL_USER_PROCESS_PARAMETERS UserProcParam;
    
    __asm {
            mov        eax, fs:[0x18]        // TEB
            mov        eax, [eax + 0x30]     // PEB
            mov        eax, [eax + 0x10]     // RTL_USER_PROCESS_PARAMETERS
            mov        UserProcParam, eax
    }
    
    MessageBoxW(NULL,
                UserProcParam->Desktop.Buffer,
                TEXT("Desktop"),
                MB_ICONINFORMATION);
}
Re[2]: Window station of a process
От: rus blood Россия  
Дата: 08.09.08 06:59
Оценка:
Здравствуйте, xmen, Вы писали:

X>Вот написал, может, подойдет:



Это же GetStartupInfo...
Это же только для хендла самого процесса...
Для этого и GetProcessWindowStation есть...

Спасибо, конечно, но нужно определять станции других процессов

Если точно, то задача звучит так.

Периодически может возникать необходимость в поиске "своих" процессов, и определении параметров их запуска. В частности, на какой станции они были запущены. Или хотя бы, интерактивно они запущены или нет. В API для работы со станциями и десктопами я такой возможности не нашел.

Вот и вопрос — пропустил я что или нет? Может, через WTS как?

ЗЫ
На самом деле, для найденных процессов есть возможность установить "легальный" ipc-канал связи, и запросить нужную информацию явно. Так что путешествия в режим ядра и прочие "фокусы" просто не требуются. Вопрос чисто для интереса...
Имею скафандр — готов путешествовать!
Re[3]: Window station of a process
От: Ivan Россия www.rsdn.ru
Дата: 08.09.08 15:03
Оценка: 3 (1)
Здравствуйте, rus blood, Вы писали:

RB>Это же GetStartupInfo...

RB>Это же только для хендла самого процесса...
RB>Спасибо, конечно, но нужно определять станции других процессов

Этот код, после небольшой доработки подойдет и для других процессов.
Сначала нужно получить PEB процесса с помощью NtQueryInformationProcess
http://msdn.microsoft.com/en-us/library/ms684280(VS.85).aspx

typedef struct _PROCESS_BASIC_INFORMATION {
PVOID Reserved1;
PPEB PebBaseAddress;
PVOID Reserved2[2];
ULONG_PTR UniqueProcessId;
PVOID Reserved3;
} PROCESS_BASIC_INFORMATION;


А затем с помощью ReadProcessMemory читать непосредственно в памяти процесса нужные структуры (RTL_USER_PROCESS_PARAMETERS и т.п.)
Нужно учесть x64 — из wow64 процесса не получится читать память native процесса по адресам, выше 4 гб
Re[3]: Window station of a process
От: xmen  
Дата: 08.09.08 16:32
Оценка:
Здравствуйте, rus blood, Вы писали:
RB>Периодически может возникать необходимость в поиске "своих" процессов, и определении параметров их запуска. В частности, на какой станции они были запущены. Или хотя бы, интерактивно они запущены или нет. В API для работы со станциями и десктопами я такой возможности не нашел.

Можно все считать через ReadProcessMemory примерно так:
#pragma comment(linker, "-subsystem:windows")
#pragma comment(linker, "-entry:main")
#pragma comment(lib, "kernel32")
#pragma comment(lib, "user32")

#define UNICODE
#include <windows.h>

typedef struct _UNICODE_STRING {
  USHORT Length;        /* bytes */
  USHORT MaximumLength; /* bytes */
  PWSTR  Buffer;
} UNICODE_STRING, *PUNICODE_STRING;

typedef struct _CURDIR
{
    UNICODE_STRING DosPath;
    PVOID Handle;
} CURDIR, *PCURDIR;

typedef struct RTL_DRIVE_LETTER_CURDIR
{
    USHORT              Flags;
    USHORT              Length;
    ULONG               TimeStamp;
    UNICODE_STRING      DosPath;
} RTL_DRIVE_LETTER_CURDIR, *PRTL_DRIVE_LETTER_CURDIR;

typedef struct _RTL_USER_PROCESS_PARAMETERS
{
    ULONG               AllocationSize;
    ULONG               Size;
    ULONG               Flags;
    ULONG               DebugFlags;
    HANDLE              ConsoleHandle;
    ULONG               ConsoleFlags;
    HANDLE              hStdInput;
    HANDLE              hStdOutput;
    HANDLE              hStdError;
    CURDIR              CurrentDirectory;
    UNICODE_STRING      DllPath;
    UNICODE_STRING      ImagePathName;
    UNICODE_STRING      CommandLine;
    PWSTR               Environment;
    ULONG               dwX;
    ULONG               dwY;
    ULONG               dwXSize;
    ULONG               dwYSize;
    ULONG               dwXCountChars;
    ULONG               dwYCountChars;
    ULONG               dwFillAttribute;
    ULONG               dwFlags;
    ULONG               wShowWindow;
    UNICODE_STRING      WindowTitle;
    UNICODE_STRING      Desktop;
    UNICODE_STRING      ShellInfo;
    UNICODE_STRING      RuntimeInfo;
    RTL_DRIVE_LETTER_CURDIR DLCurrentDirectory[0x20];
} RTL_USER_PROCESS_PARAMETERS, *PRTL_USER_PROCESS_PARAMETERS;

LPVOID GetLPPEB()
{
    LPVOID r;
    __asm {
            mov        eax, fs:[0x18]
            add        eax, 0x30
            mov        r, eax
    }
    return r;
}

main()
{

    RTL_USER_PROCESS_PARAMETERS UserProcParam;

    DWORD dwProcessId = 3700; // PID процесса
    HANDLE hProcess;
    
    if (hProcess = OpenProcess(PROCESS_ALL_ACCESS,
                               FALSE,
                               dwProcessId))
    {
        DWORD PEB;
        ReadProcessMemory(hProcess,
                          GetLPPEB(),
                          &PEB,
                          sizeof(PEB),
                          0);
        
        PEB += 0x10;
        LPVOID LPUserProcParam;
        ReadProcessMemory(hProcess,
                          (LPVOID) PEB,
                          &LPUserProcParam,
                          sizeof(LPUserProcParam),
                          0);
        
        ReadProcessMemory(hProcess,
                          LPUserProcParam,
                          &UserProcParam,
                          sizeof(UserProcParam),
                          0);
        
        LPWSTR Desktop = (LPWSTR) HeapAlloc(GetProcessHeap(),
                                            HEAP_ZERO_MEMORY,
                                            UserProcParam.Desktop.Length + 1);
        ReadProcessMemory(hProcess,
                          UserProcParam.Desktop.Buffer,
                          Desktop,
                          UserProcParam.Desktop.Length,
                          0);

        LPWSTR ComLine = (LPWSTR) HeapAlloc(GetProcessHeap(),
                                            HEAP_ZERO_MEMORY,
                                            UserProcParam.CommandLine.Length + 1);
        ReadProcessMemory(hProcess,
                          UserProcParam.CommandLine.Buffer,
                          ComLine,
                          UserProcParam.CommandLine.Length,
                          0);
        
        MessageBoxW(NULL,
                    Desktop,
                    TEXT("Desktop"),
                    MB_ICONINFORMATION);
        
        MessageBoxW(NULL,
                    ComLine,
                    TEXT("Command Line"),
                    MB_ICONINFORMATION);
        
        HeapFree(GetProcessHeap(), NULL, Desktop);
        HeapFree(GetProcessHeap(), NULL, ComLine);
    }
}
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.