C++ 获取程序打开套接字的句柄
如何获取程序创建的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 所说,这并非微不足道.您必须为系统中的每个进程调用 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).
对于每个进程,您使用NtQuerySystemInformation
(具有SystemHandleInformation
的信息类)访问施主进程的句柄表.最后,您调用 DuplicateHandle
使进程的句柄也成为您的句柄.
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.
在枚举捐赠者进程的句柄表时,您必须过滤句柄类型.对于您复制的每个句柄,使用 ObjectTypeInformation
调用 NtQueryObject
.如果类型是套接字,则将其保持打开状态并将其放入列表中.否则,关闭它并继续.
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.
要执行比较,代码类似于下面.类型作为 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 类型(我不记得了),您应该尝试获取与句柄关联的名称(它仍然是 UNICODE_STRING
),然后查找 \设备\Tcp
.这一次,您将使用相同的句柄,但使用 ObjectNameInformation
调用 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 */ }
我自己是另一个人,几年前也做过类似的事情.我们没有使用套接字,而是使用互斥体和事件来使特权防病毒组件从其用户级 UI 程序(与 IPC 的特权组件共享句柄)中崩溃.请参阅旧狗和新把戏:你知道你的把手在哪里吗?.
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?.
相关文章