本人并未在“迅游加速器”有个任何从业经历,与迅游相关的,仅仅只是对“加速器原理”有一些相关的研究但也就仅此而已,你想想我这一个搞“dotNET”被大陆社会抛弃的人啊,哪能会这些高端玩意呢,哈哈!
本人并未对“迅游加速器(LSP)”有过任何逆向分析的过程,那个壳也挺烦的,整个过程全靠悟所以有人想要举报我也没用,咋合理研究不犯法,我们仅仅只是对隐藏在技术中真谛有一种小小的执着而已。
迅游加速器分了两层,一个迅游加速器的主界面(宿主进程),它主要是侦听一个固定的转发端口,LSP分层DLL,主要是为了hook应用的套接字链接。
我曾经一直没有想明白它是怎么一个端口搞定让它的“主进程”知道流量应该往那个服务器发送的,而我实现过类似的东西叫“PaperAirplane”,但它主要是为了验证LSP/NSP脱离DNS污染娱乐的东西的一种思路,但与这些LSP类的加速器应该是属于同类的东西。
在很久前的一个时间里我突然想明白了,这个问题。说实话这个东西有那么一点小巧妙我对这个东西一下就来了很多兴趣,它并不复杂甚至并没有一个太高的技术复杂度,但我却在这里走进了一个思维误区,认为只要链接未连接上服务器那么Socket就不具有LocalEndPoint(getsockname)但现在想来并非是如此的。
Socket只要创建出来,它不一定具有 LocalEndPoint 这是合理的,它在套接字 Bind 后才会构建“LocalEndPoint”但万事算漏一点 Connect 函数只要向目标服务器连接,若socket未被bind一个网卡与接口端口,那么“mswsock”会为此立即分配一个可用的 LocalEndPoint(local ipep)。
看到这里很多人应该反应过来了,对的,迅游的LSP的DLL它仅仅只是在应用程序socket connect时把链接的地址,直接改成“迅游宿主进程”侦听的端口,同时向“迅游宿主进程”发送消息,而且据我本人的研究,例如:“迅游、网易UU”加速器基本都是这么干的,就是说向指定className的窗口句柄发送消息,否则就是向“全局内存共享”中定义契约的结构,在结构上指定了窗口句柄,发送消息,八九不离十肯定就是这么干的,还有另一点足够让我肯定的是我在“PaperAirplane”中已经论证了这个方法的可行性。
int WSPAPI WSPConnect(SOCKET s, const struct sockaddr* name, int namelen, LPWSABUF lpCallerData, LPWSABUF lpCalleeData, LPQOS lpSQOS,
LPQOS lpGQOS, LPINT lpErrno)
BOOL PASCAL ConnectEx(SOCKET s, const sockaddr* name, int namelen, PVOID lpSendBuffer, DWORD dwSendDataLength, LPDWORD lpdwBytesSent,
LPOVERLAPPED lpOverlapped)
迅游的LSP/DLL实现TCP的桥接转发,它只需要在lsp中hook上面的两个方法就可以,而且搞起来非常的简单,一天时间你就能把它搞出来(当然是知道方法怎么弄的前提下,单纯依靠研究就比较费时间了),但LSP本身也具有一些问题,应用层是可以通过一些机制防护不加载LSP的DLL的,至于程序有防护又是怎么加载进去的这个暂时没的太明白,系统有一些设置可以搞但作用几乎没有,所以我个更倾向于这些DLL的证书太高级了,另一点是LSP的厂商跟这些应用厂商有不正常黑暗的秘密交易,但大多数情况下游戏厂商对加速器都比较友好(可以提高玩家游戏体验的嘛,这可以为游戏带来更多的利润),不过一般情况大多数程序都会加载LSP的dll。
UDP的话搞法子类似,只需要在LSP中HOOK下面的几个方法就可以搞定了,这里主要讲“宿主进程UDP只侦听一个端口转发的方法”,利用“端口一对一映射”方式是最简单的。
在LSP中把应用程序要udp发送的目标端口替换成“迅游宿主进程”侦听的端口,但是要对“原始的数据包”动点手脚,在hook发送给“迅游宿主进程”的数据包头上加点信息(目标的服务器、端口号啊这些)本机环路UDP不存在丢包随便UDP怎么发都不是问题,重发都不用管,以下是UDP要在lsp中hook的两个函数。
INT PASCAL SendMsgEx(SOCKET s, LPWSAMSG lpMsg, DWORD dwFlags, LPDWORD lpNumberOfBytesSent, LPWSAOVERLAPPED lpOverlapped,
LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
int WSPAPI WSPSendTo(SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount, LPDWORD lpNumberOfBytesSent, DWORD dwFlags, const struct sockaddr FAR * lpTo,int iTolen, LPWSAOVERLAPPED lpOverlapped, LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine, LPWSATHREADID lpThreadId, LPINT lpErrno)
“迅游宿主进程”收到这个包以后把它打包发送给“迅游的代理转发服务器”,“迅游的代理转发服务器”再把这个数据发送给目标的服务器。
上面一直没提到回来的数据改怎么回转给LSP/hook的程序,它不一定是单个服务器可能是多个服务器(理想情况肯定是一对一,但现实情况并不一定是),所以这就是UDP服务器虚拟化方面的问题了。
“迅游宿主进程”收到了服务器转发过来的数据包按目标的端口与地址,然后自己在虚拟一个UDP的套接字出来随便绑定一个端口与之对应,然后向利用这个套接字向与被hook的那个应用程序端口转发数据包,这个时候hook的那个应用程序收到数据端口就是不一样的,这就解决了这些问题。
当然这些方法也有缺陷,就是被hook的应用需要要是检查,udp数据包来源的服务器地址是不是内网的就要出问题,不过这种可能太低了,所以这些LSP的加速器就越来越猖狂了哈!