プログラムの作成されたソケットのソケット ID (ハンドル) を取得するにはどうすればよいですか?
すべてのプログラムですべての開いているソケットを取得できることはわかっていますGetTcpTable()
が、2 つの問題があります。
- すべてのプログラムソケットを表示します
- ソケットの ID (ハンドル) を返しません
レミーが言ったように、それは些細なことではありません。システム内のプロセスごとに呼び出す必要がOpenProcess
あります。andPROCESS_DUP_HANDLE
も必要かもしれませんが、私はそれを必要としたことはありません (それを使用する他のコードを見たことがあります)。PROCESS_QUERY_INFORMATION
PROCESS_VM_READ
プロセスごとに、ドナー プロセスのハンドル テーブルにNtQuerySystemInformation
( の情報クラスでSystemHandleInformation
) アクセスします。最後にDuplicateHandle
、プロセスのハンドルを自分のハンドルにするために呼び出します。
ドナー プロセスのハンドル テーブルを列挙するときは、ハンドルの種類をフィルター処理する必要があります。複製したハンドルごとに、 を呼び出しNtQueryObject
ますObjectTypeInformation
。タイプがソケットの場合は、開いたままにしてリストに入れます。それ以外の場合は、閉じて続行します。
比較を実行するためのコードは、次のようになります。タイプは次のように返されます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
です)、 を探す必要があります\\Device\\Tcp
。今回は、同じハンドルを使用しますが、次のように呼び出しNtQueryObject
ます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 の特権コンポーネントとハンドルを共有していた) から特権アンチウイルス コンポーネントをクラッシュさせました。古い犬と新しいトリックを見る: ハンドルがどこにあるか知っていますか? .