使用detours Hook IE11 中 WSARecv WSASend CreateThreadpoolIo StartThreadpoolIo CancelThreadpoolIo在IE11中
有效另外Hook的其它API 如WSAGetOverlappedResult GetQueuedCompletionStatus WaitForThreadpoolIoCallbacks
GetQueuedCompletionStatusEx 等等在IE11下就没有作用,在Hook WSARecv 中出现问题了,我做的hook是使用
webbrowser进行的。
在ie11中开始打开网页时会出现好几个socket 与closesocket的无数据操作的SOCKET在以前ie8的版本就好像没出现过,
不知这是什么原因。
先说一下我Hook的过程,IE11内核中socket 的通讯是通过完成端口进行的,首先是调用ws2_32.dll 中的 WSASocketA
WSASocketW 有时一个SOCKET 两个函数都进去了,这个有点不明白,再进入socket调用,这里为什么WSASocke
socket 两个版本在同一个SOCKET上都会调用呢?
进入CreateThreadpoolIo中建立SOCKET与IO 的联系,这是要保存每一对SOCKET 与 IO 的数据还要加一个回调地址。
PTP_IO __stdcall Mine_CreateThreadpoolIo(HANDLE fl,
PTP_WIN32_IO_CALLBACK pfnio, PVOID pv, PTP_CALLBACK_ENVIRON pcbe)
{
char szBuf[255];
PTP_IO rv = 0;
__try {//MyPTPFun
rv = Real_CreateThreadpoolIo(fl,MyPTPFun,pv,pcbe);
sprintf(szBuf,"CreateThreadpoolIo: S:0x%08x IO:0x%08x FUN:0x%08x\r\n",fl,rv,pfnio);HuiOutDebug(szBuf,_T("hookApi"));
g_manage.BingSocketToIo(rv,(SOCKET)fl,(void*)pfnio);//这里就是保存操作。
} __finally {
};return rv;
}
VOID __stdcall MyPTPFun(PTP_CALLBACK_INSTANCE Instance,PVOID Context,PVOID Overlapped,
ULONG IoResult,ULONG_PTR NumberOfBytesTransferred,PTP_IO Io)
{
char szBuf[255];
PTP_WIN32_IO_CALLBACK pFun= (PTP_WIN32_IO_CALLBACK)g_manage.GetIoFun(Io);
sprintf(szBuf,"MyPTPFun: IO:0x%08x FUN:0x%08x\r\n",Io,pFun);HuiOutDebug(szBuf,_T("hookApi"));
if( pFun ){
g_manage.ProceIo(Io,Overlapped,Context,IoResult,NumberOfBytesTransferred);//先调用自的的回调函数,就是这里出现漏数据?????
pFun(Instance,Context,Overlapped,IoResult,NumberOfBytesTransferred,Io);//然后是原回调函数
}
} //g_manage是一个保存数据的全局类,类中使用了CCriticalSection m_sc;对所用操作进行了保护。
进入StartThreadpoolIo操作,也就是设备IO与SOCKET的一次数据操作正式建立联系。
连接操作不是WSAConnect与connect,是进入connectEx ,这个函数的Hook 比较麻烦,后面我会说明这个函数是怎么hook的,
在IE8中在hook connect时就会出出两个握手的操作,send 与recv,发送与接收的只有一个字节或没有字节,但IE11中只进入了recv,那个send没进入,握手操作的发送数据据不知是怎么操作,这是什么原因呢?
connectEx 之后没有send 或WSASend 操作,直接进入了回调函数MyPTPFun ,MyPTPFun之后没有调用StartThreadpoolIo直接进入recv操作,有时recv与没有操作。
连接建立后,再次进入StartThreadpoolIo进行设备IO与SOCKET的一次数据操作建立联系。
进入WSASend,好像这个函数的操作能立即完成似的没进入回调MyPTPFun中,直接CancelThreadpoolIo取消io完成端口的回调。
再次进入StartThreadpoolIo进行设备IO与SOCKET的一次数据操作建立联系。
然后就是WSARecv,这个操作有时能立即完成直接CancelThreadpoolIo取消io完成端口的回调。有时进入回调函数MyPTPFun,
int __stdcall Mine_WSARecv(SOCKET a0,LPWSABUF a1,DWORD a2,LPDWORD a3,LPDWORD a4,
LPWSAOVERLAPPED a5,LPWSAOVERLAPPED_COMPLETION_ROUTINE a6)
{ int rv = 0;
DWORD dw;
DWORD dwLen ,dwLen1;
LPWSABUF lp;
char szBuf[500];
__try {
rv = Real_WSARecv(a0, a1, a2, a3, a4, a5, a6);
sprintf(szBuf,"WSARecv:s:0x%08x Len:%d len:%d\r\n",a0,0,a1[0].len);
HuiOutDebug(szBuf,_T("hookApi"));
g_manage.SetOp(a0,2,a1,a2,a5,a1[0].len);//这里进行了保存操作,以便观察对比;
} __finally {
};
return rv;
}
}
在上述的过程中,g_manage.BingSocketToIo 对回调,完成设备IO, 套接字建立了数据联系,g_manage.SetOp对接收或发送
数据的 LPWSAOVERLAPPED LPWSABUF 指针进行了保存,以便取数或观察。其中在我的回调中对LPWSABUF进行观察时出现了原有的数据消失了,这个应该是new 产生的,因为我对原WSARecv LPWSABUF 结构中len进行了保存,发现是1024,可是在MyPTPFun -> g_manage.ProceIo 进行对比时,原LPWSABUF 指针结构中的len 不是1024了是很大的一个数,这是不可能的,结论就是原WSARecv 中new 产生的LPWSABUF 被释放了,因为调用MyPTPFun 回调就意味着WSARecv返回时,数据应该没收到,但在MyPTPFun 时,原LPWSABUF又被释放了,那IE11在WSARecv 返回与MyPTPFun 回调间是用什么来取数据的呢?还有其它的API吗?在MyPTPFun 中,是我先观察,再调用IE11给的回调函数的。完成端口CreateThreadpoolIo StartThreadpoolIo 的这套API还有别的能取数吗?WaitForThreadpoolIoCallbacks这个api没有进入过,GetQueuedCompletionStatus这个API应该与CreateThreadpoolIo 不是一个体系的吧!
整个hook过程中对进入的API WSASocketW WSASocketA CreateThreadpoolIo StartThreadpoolIo connectex recv WSARecv WSASend socket closesocket 进行了记事本输出观察。
下面结出调用的过程(整理的)
WSASocketW:s:0x00000448
WSASocketA:s:0x00000448
CreateThreadpoolIo: S:0x00000448 IO:0x0052f7a8 FUN:0x7601dfb0
StartThreadpoolIo:IO:0x0052f7a8
connectex:s:0x00000448
MyPTPFun: IO:0x0052f7a8 FUN:0x7601dfb0
StartThreadpoolIo:IO:0x0052f7a8
WSASend:s:0x00000448 Len:0 len:770
CancelThreadpoolIo:IO:0x0052f7a8
WSARecv:s:0x00000448 Len:0 len:1024
MyPTPFun: IO:0x0052f7a8 FUN:0x7601dfb0
StartThreadpoolIo:IO:0x0052f7a8
WSARecv:s:0x00000448 Len:0 len:4096
CancelThreadpoolIo:IO:0x0052f7a8
StartThreadpoolIo:IO:0x0052f7a8
WSARecv:s:0x00000448 Len:0 len:4096
CancelThreadpoolIo:IO:0x0052f7a8
StartThreadpoolIo:IO:0x0052f7a8
WSARecv:s:0x00000448 Len:0 len:4096
CancelThreadpoolIo:IO:0x0052f7a8
WSARecv:s:0x00000448 Len:0 len:4096
CancelThreadpoolIo:IO:0x0052f7a8
StartThreadpoolIo:IO:0x0052f7a8
WSARecv:s:0x00000448 Len:0 len:4096
CancelThreadpoolIo:IO:0x0052f7a8
StartThreadpoolIo:IO:0x0052f7a8
WSARecv:s:0x00000448 Len:0 len:4096
CancelThreadpoolIo:IO:0x0052f7a8
StartThreadpoolIo:IO:0x0052f7a8
WSARecv:s:0x00000448 Len:0 len:4096
CancelThreadpoolIo:IO:0x0052f7a8
recv:s:0x00000448 Len:-1
recv:s:0x00000448 Len:-1
StartThreadpoolIo:IO:0x0052f7a8
WSASend:s:0x00000448 Len:0 len:867
CancelThreadpoolIo:IO:0x0052f7a8
WSARecv:s:0x00000448 Len:0 len:1024
MyPTPFun: IO:0x0052f7a8 FUN:0x7601dfb0
WSASocketW:s:0x0000043c
WSASocketA:s:0x0000043c
CreateThreadpoolIo: S:0x0000043c IO:0x0052f688 FUN:0x7601dfb0
StartThreadpoolIo:IO:0x0052f688
connectex:s:0x0000043c
MyPTPFun: IO:0x0052f688 FUN:0x7601dfb0
recv:s:0x0000043c Len:-1
recv:s:0x0000043c Len:-1
StartThreadpoolIo:IO:0x0052f688
WSASend:s:0x0000043c Len:0 len:708
CancelThreadpoolIo:IO:0x0052f688
StartThreadpoolIo:IO:0x0052f688
WSARecv:s:0x0000043c Len:0 len:1024
MyPTPFun: IO:0x0052f688 FUN:0x7601dfb0
StartThreadpoolIo:IO:0x0052f688
WSARecv:s:0x0000043c Len:0 len:4096
CancelThreadpoolIo:IO:0x0052f688
recv:s:0x0000043c Len:-1
WSASocketW:s:0x00000354
socket:s:0x00000354
closesocket:s:0x00000354
WSASocketW:s:0x00000354
WSASocketA:s:0x00000354
CreateThreadpoolIo: S:0x00000354 IO:0x004d8f48 FUN:0x7601dfb0
StartThreadpoolIo:IO:0x004d8f48
connectex:s:0x00000354
MyPTPFun: IO:0x004d8f48 FUN:0x7601dfb0
recv:s:0x00000354 Len:-1