大概描述下完成端口的原理
一个套接字可以对应多个overlapped, 每个overlapped都由相应的一个线程来处理。而WSARecv绑定好了一个OVERLAPPED,WSARecv的调用会通知数据即将到来,同时将会触发某线程中的GetQueuedCompletionStatus函数调用完成,然后通过第四个参数OVERLAPPED的某个偏移得到回包j然后进行后续操作。相应的WSASend也是一个同样的调用过程。
调试回包最开始的思路在关键API下断找到真正的回包数据
通过刚才的原理已经知道直接在GetQueuedCompletionStatus这函数下断是不行的,因为发包和回包都会回调这个函数,必须通过某种方式区分发包和回包。很显然方法就是先在WSARecv下断然后再GetQueuedCompletionStatus下断。同时通过观察找到BUFFER位于输出参数OVERLAPPED的偏移位置,于是找到取到回包的内容。
下断关键点
试对WSARECV,GetQueuedCompletionStatus分别hook,通过WSARecv输入参数overlapped与GetQueuedCompletionStatus的输出参数overlapped 匹配得到buffer地址,即得到回包内容。注意匹配的过程需要考虑多线程环境。因为WSARecv和GetQueuedCompletionStatus都是不同线程在调用。
实战
在实战过程中,找解密函数,其实只需要先对WSARecv下断,再对输出buffer下硬件访问断点即可,因为只有回包有数据并且当前进程对其进行数据操作的时候才会被断下来,而数据具体填buffer的过程,并不会触发断点,估计这个过程是在ring0层实现的。