問題描述
如何獲取程序創(chuàng)建的socket的Socket ID(句柄)?
How is it possible to get the Socket ID (Handle) of the created sockets of a program?
我知道我可以通過 GetTcpTable()
獲取所有程序中所有打開的套接字,但它有兩個問題:
I know I can get all the open sockets in all programs by GetTcpTable()
but it has two problems:
- 它顯示所有程序套接字
- 它不返回套接字的 ID(句柄)
推薦答案
正如 Remy 所說,這并非微不足道.您必須為系統(tǒng)中的每個進(jìn)程調(diào)用 OpenProcess
和 PROCESS_DUP_HANDLE
.您可能還需要 PROCESS_QUERY_INFORMATION
和 PROCESS_VM_READ
,但我從不需要它(我見過使用它的其他代碼).
As Remy said, its not trivial. You have to call OpenProcess
with PROCESS_DUP_HANDLE
for each process in the system. You might also need PROCESS_QUERY_INFORMATION
and PROCESS_VM_READ
, but I've never needed it (I've seen other code that uses it).
對于每個進(jìn)程,您使用NtQuerySystemInformation
(具有SystemHandleInformation
的信息類)訪問施主進(jìn)程的句柄表.最后,您調(diào)用 DuplicateHandle
使進(jìn)程的句柄也成為您的句柄.
For each process, you access the donor process's handle table with NtQuerySystemInformation
(with an information class of SystemHandleInformation
). Finally, you call DuplicateHandle
to make the process's handle your handle, too.
在枚舉捐贈者進(jìn)程的句柄表時,您必須過濾句柄類型.對于您復(fù)制的每個句柄,使用 ObjectTypeInformation
調(diào)用 NtQueryObject
.如果類型是套接字,則將其保持打開狀態(tài)并將其放入列表中.否則,關(guān)閉它并繼續(xù).
You will have to filter the handle types when enumerating the donor process's handle table. For each handle you have duplicated, call NtQueryObject
with ObjectTypeInformation
. If the type is a socket, you keep it open and put it in your list. Otherwise, close it and go on.
要執(zhí)行比較,代碼類似于下面.類型作為 UNICODE_STRING
返回:
To perform the compare, the code looks similar to below. The type is returned as a UNICODE_STRING
:
// info was returned from NtQueryObject, ObjectTypeInformation
POBJECT_TYPE_INFORMATION pObjectTypeInfo = (POBJECT_TYPE_INFORMATION)(LPVOID)info;
wstring type( pObjectTypeInfo->Name.Buffer, pObjectTypeInfo->Name.Length );
if( 0 != wcscmp( L"Socket", type.c_str() ) ) { /* Not a Socket */ }
如果沒有 Socket 類型(我不記得了),您應(yīng)該嘗試獲取與句柄關(guān)聯(lián)的名稱(它仍然是 UNICODE_STRING
),然后查找 \設(shè)備\Tcp
.這一次,您將使用相同的句柄,但使用 ObjectNameInformation
調(diào)用 NtQueryObject
:
If there is no Socket type (I don't recall), you should try to get the name associated with the handle (its still a UNICODE_STRING
), and look for \Device\Tcp
. This time, you would use the same handle, but call NtQueryObject
with ObjectNameInformation
:
// info was returned from NtQueryObject, ObjectNameInformation
POBJECT_NAME_INFORMATION pObjectNameInfo = (POBJECT_NAME_INFORMATION)(LPVOID)info;
wstring name( pObjectNameInfo->Name.Buffer, pObjectNameInfo->Name.Length );
if( name.substr(0, 11) == "\Device\Tcp" ) ) { /* It's a TCP Socket */ }
我自己是另一個人,幾年前也做過類似的事情.我們沒有使用套接字,而是使用互斥體和事件來使特權(quán)防病毒組件從其用戶級 UI 程序(與 IPC 的特權(quán)組件共享句柄)中崩潰.請參閱舊狗和新把戲:你知道你的把手在哪里嗎?.
Myself an another fellow did similar a few years ago. Instead of Sockets, we used Mutexes and Events to crash privileged Antivirus components from their userland UI program (which was sharing handles with the privileged component for IPC). See Old Dogs and New Tricks: Do You Know Where Your Handles Are?.
這篇關(guān)于C++ 獲取程序打開套接字的句柄的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網(wǎng)!