如何获取程序创建的套接字的套接字 ID(句柄)?
我知道我可以通过以下方式获得所有程序中的所有打开套接字,GetTcpTable()
但它有两个问题:
- 它显示所有程序套接字
- 它不返回套接字的 ID(句柄)
正如雷米所说,这不是微不足道的。您必须为系统中的每个进程调用OpenProcess
with PROCESS_DUP_HANDLE
。您可能还需要PROCESS_QUERY_INFORMATION
and 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 类型(我不记得了),您应该尝试获取与句柄关联的名称(它仍然是 a 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 */ }
几年前,我自己和另一个人也做过类似的事情。我们使用互斥锁和事件来替代 Sockets,从他们的用户态 UI 程序(与 IPC 的特权组件共享句柄)中崩溃特权防病毒组件。见老狗和新把戏:你知道你的把手在哪里吗?.
好的,感谢所有试图解决我的问题的人
经过大量工作后,我知道如何自己处理它,这就是我尝试获取指定套接字的方式:
如图所示,在 0x467781 处调用了 Socket 发送函数,并将 Socket 句柄保存到 EDX 寄存器中的堆栈中
现在我需要做的是将我的代码挂钩到该函数中。
void GetSocket(int Flag,int DataSize, char* Data, SOCKET Socket)
{
sSocket = Socket;
sFlag = Flag;
sDataSize = DataSize;
sData = Data;
SendPacket(sSocket,Data,DataSize); //Send packets manually
}
__declspec(naked) void MyFunc()
{
__asm
{
PUSH EDX // Socket
PUSH ECX // Buffer
PUSH EAX // Buffer Size
PUSH 0 // Flag
CALL GetSocket
MOV EAX, sDataSize
MOV ECX, sData
MOV EDX, sWowSocket
JMP [JumpAddress] // JumpAddress = 0x467787 (After that CALL)
}
}
现在我要做的就是将 CALL(在 0x467781 中)更改为 JMP 到我们的函数(MyFunc),它可以通过以下函数完成:
*(DWORD*) (0x467781 + 0x01) = (DWORD)MyFunc- (0x467781 + 0x05);
现在我完成了,我可以很容易地看到它发送到服务器的每个数据包,并在必要时更改它们,还可以通过它的 Socket 发送我的自定义数据包:)