Но еще хотелось бы иметь PID процесса-владельца этих ресурсов. Чтение доки не особо помогло - например есть такая
Пришлось как обычно кряхтя слазить с печи и делать все самому
Например начать всегда хорошо с курения сорцов - в данном случае WRK v1.2
В файле base\ntos\lpc\lpcconn.c есть все что нам нужно - можно открыть порт через ObReferenceObjectByName с типом LpcPortObjectType или LpcWaitablePortObjectType и получить внутреннее представление объекта port в виде структуры LPCP_PORT_OBJECT, которая описана в base\ntos\inc\lpc.h так:
#define PORT_TYPE 0x0000000F
#define SERVER_CONNECTION_PORT 0x00000001
#define UNCONNECTED_COMMUNICATION_PORT 0x00000002
#define SERVER_COMMUNICATION_PORT 0x00000003
#define CLIENT_COMMUNICATION_PORT 0x00000004
#define PORT_WAITABLE 0x20000000
#define PORT_NAME_DELETED 0x40000000
#define PORT_DYNAMIC_SECURITY 0x80000000
typedef struct _LPCP_PORT_QUEUE {
PLPCP_NONPAGED_PORT_QUEUE NonPagedPortQueue;
PKSEMAPHORE Semaphore; // Counting semaphore that is incremented
// whenever a message is put in receive queue
LIST_ENTRY ReceiveHead; // list of messages to receive
} LPCP_PORT_QUEUE, *PLPCP_PORT_QUEUE;
typedef struct _LPCP_PORT_OBJECT {
struct _LPCP_PORT_OBJECT *ConnectionPort;
struct _LPCP_PORT_OBJECT *ConnectedPort;
LPCP_PORT_QUEUE MsgQueue;
CLIENT_ID Creator;
PVOID ClientSectionBase;
PVOID ServerSectionBase;
PVOID PortContext;
PETHREAD ClientThread; // only SERVER_COMMUNICATION_PORT
SECURITY_QUALITY_OF_SERVICE SecurityQos;
SECURITY_CLIENT_CONTEXT StaticSecurity;
LIST_ENTRY LpcReplyChainHead; // Only in _COMMUNICATION ports
LIST_ENTRY LpcDataInfoChainHead; // Only in _COMMUNICATION ports
union {
PEPROCESS ServerProcess; // Only in SERVER_CONNECTION ports
PEPROCESS MappingProcess; // Only in _COMMUNICATION ports
};
USHORT MaxMessageLength;
USHORT MaxConnectionInfoLength;
ULONG Flags;
KEVENT WaitEvent; // Object is truncated for non-waitable ports
} LPCP_PORT_OBJECT, *PLPCP_PORT_OBJECT;
Как видим все довольно просто, но как обычно без засады не обошлось - LpcWaitablePortObjectType не экспортируется. Я плюнул и забил - оказалось что rpc порты и с типом LpcPortObjectType отлично открываются.
По получении PLPCP_PORT_OBJECT проверяем что это именно серверный порт ((Flags & PORT_TYPE) == SERVER_CONNECTION_PORT) и извлекаем PID из поля ServerProcess с помощью функции PsGetProcessId (на w2k работать не будет. Впрочем если верить Русиновичу - смещение на поле EPROCESS.UniqueProcessId равно 0x9c)
Небольшой кусочек лога на xp 32bit:
Port: protected_storageЗапускаем на vista/w7 - получаем какой-то треш. Долго нервно курим, читаем доку - обретаем просветление - начиная с vista RPC использует другой тип объектов - ALPC Port. Медитация в отладчике говорит, что вместо LPCP_PORT_OBJECT ObReferenceObjectByName возвращает нам PALPC_PORT (взято с windows 7 64bit):
Flags: 1, server 988 (C:\WINDOWS\system32\lsass.exe)
Port: audit
Flags: 1, server 988 (C:\WINDOWS\system32\lsass.exe)
Port: spoolss
Flags: 1, server 800 (C:\WINDOWS\system32\spoolsv.exe)
Port: securityevent
Flags: 1, server 988 (C:\WINDOWS\system32\lsass.exe)
Port: IUserProfile
Flags: 1, server 932 (C:\WINDOWS\system32\winlogon.exe)
Port: DNSResolver
Flags: 1, server 176 (C:\WINDOWS\system32\svchost.exe)
dt _ALPC_PORT
+0x000 PortListEntry : _LIST_ENTRY
+0x010 CommunicationInfo : Ptr64 _ALPC_COMMUNICATION_INFO
+0x018 OwnerProcess : Ptr64 _EPROCESS
+0x020 CompletionPort : Ptr64 Void
+0x028 CompletionKey : Ptr64 Void
+0x030 CompletionPacketLookaside : Ptr64 _ALPC_COMPLETION_PACKET_LOOKASIDE
+0x038 PortContext : Ptr64 Void
+0x040 StaticSecurity : _SECURITY_CLIENT_CONTEXT
+0x088 MainQueue : _LIST_ENTRY
+0x098 PendingQueue : _LIST_ENTRY
+0x0a8 LargeMessageQueue : _LIST_ENTRY
+0x0b8 WaitQueue : _LIST_ENTRY
+0x0c8 Semaphore : Ptr64 _KSEMAPHORE
+0x0c8 DummyEvent : Ptr64 _KEVENT
+0x0d0 PortAttributes : _ALPC_PORT_ATTRIBUTES
+0x118 Lock : _EX_PUSH_LOCK
+0x120 ResourceListLock : _EX_PUSH_LOCK
+0x128 ResourceListHead : _LIST_ENTRY
+0x138 CompletionList : Ptr64 _ALPC_COMPLETION_LIST
+0x140 MessageZone : Ptr64 _ALPC_MESSAGE_ZONE
+0x148 CallbackObject : Ptr64 _CALLBACK_OBJECT
+0x150 CallbackContext : Ptr64 Void
+0x158 CanceledQueue : _LIST_ENTRY
+0x168 SequenceNo : Int4B
+0x16c u1 :
+0x170 TargetQueuePort : Ptr64 _ALPC_PORT
+0x178 TargetSequencePort : Ptr64 _ALPC_PORT
+0x180 CachedMessage : Ptr64 _KALPC_MESSAGE
+0x188 MainQueueLength : Uint4B
+0x18c PendingQueueLength : Uint4B
+0x190 LargeMessageQueueLength : Uint4B
+0x194 CanceledQueueLength : Uint4B
+0x198 WaitQueueLength : Uint4B
Тут все еще проще - никаких флагов проверять не нужно, сразу берем OwnerProcess и суем в PsGetProcessId. Примерчик работы на windows7:
ALPC Port: senssvcСорцов давать не буду, ибо читателям детского юмористического журнала ксакеп они не помогут, а нормальным гражданам из описания и так все должно быть понятно
Flags: 0, server 940 (C:\Windows\System32\svchost.exe)
ALPC Port: lsapolicylookup
Flags: 0, server 488 (C:\Windows\System32\lsass.exe)
ALPC Port: LSMApi
Flags: 0, server 496 (C:\Windows\System32\lsm.exe)
ALPC Port: WMsgKRpc0492F0
Flags: 0, server 400 (C:\Windows\System32\wininit.exe)
ALPC Port: WindowsShutdown
Flags: 0, server 400 (C:\Windows\System32\wininit.exe)
Update: под w2k _LPCP_PORT_OBJECT выглядит так:
nt!_LPCP_PORT_OBJECT
+0x000 Length : Uint4B
+0x004 Flags : Uint4B
+0x008 ConnectionPort : Ptr32 _LPCP_PORT_OBJECT
+0x00c ConnectedPort : Ptr32 _LPCP_PORT_OBJECT
+0x010 MsgQueue : _LPCP_PORT_QUEUE
+0x020 Creator : _CLIENT_ID
+0x028 ClientSectionBase : Ptr32 Void
+0x02c ServerSectionBase : Ptr32 Void
+0x030 PortContext : Ptr32 Void
+0x034 MaxMessageLength : Uint4B
+0x038 MaxConnectionInfoLength : Uint4B
+0x03c ClientThread : Ptr32 _ETHREAD
+0x040 SecurityQos : _SECURITY_QUALITY_OF_SERVICE
+0x04c StaticSecurity : _SECURITY_CLIENT_CONTEXT
+0x088 LpcReplyChainHead : _LIST_ENTRY
+0x090 LpcDataInfoChainHead : _LIST_ENTRY
+0x098 ServerProcess : Ptr32 _EPROCESS
+0x098 MappingProcess : Ptr32 _EPROCESS
+0x09c Reserved : Uint4B
+0x0a0 WaitEvent : _KEVENT
Комментариев нет:
Отправить комментарий