请参考如下的QQ显示IP原理分析:
到QQ2008为至,可爱的珊瑚版本显IP显隐身的QQ已经不能用了,前几天下载了比特版本,传美版本,极速版本用了一下,感觉没有珊瑚虫的版本好用,总之用习惯了一种版本,不乐意改变太多.于是抱着这种心态,我于前天下午认真研究了QQ显IP显隐身的原理,自己成功编译出了一款比较满意的显IP显隐身的QQ2008贺岁版本,以满足自己工作和学习的需要.下面我来谈一下显IP显隐身的基本原理.
大家的思路是这样子的,由于如果你现在需要和一个QQ好友传输文件或者进行语音聊天或者发送了图片或自定义表情。那么QQ必须知道对方的IP地址和端口信息,这样才能把数据传给对方。所以,QQ内部已经实现了获取IP地址和其他信息的相关函数了。的确如此。而我们只要想办法调用QQ内部的函数。
经过反编译QQ组件之一的CQQApplication.dll中的汇编代码:
027832C7
027832CA
027832CB
027832D0
027832D1
027832D3
027832D6
027832D9
027832DA
027832DF
027832E0
027832E2
直接修改QQ本身的程序文件->不具备版本无关性,容易引发法律纠纷
使用外部exe进程->必须采用调试进程的办法,效率低且浪费系统资源
编写dll文件让QQ加载->效率高,稳定
所以我们都选择了第三种编写DLL注入的方法,一般目前显IP的版本下面都有两个这样的文件,FINEPLUS.exe和fineplus.dll,我们一般通过fineplus.exe来启动QQ,从而实现显IP的目的,大家可能以为主要的功能部分一定在fineplus.exe这个文件中,其实是不对的,fineplus.exe这个文件就做了一件事,就是在启动QQ的过程中把fineplus.dll注入到QQ中去.
将dll文件注入到程序的方法有2种:
1.首先通过CreateProcess创建进程,然后模拟windows加载一个dll的全过程,在加载程序主体
2.采用远程线程植入技术,即使用CreateRemoteThread
我也只是参考了明日帝国的教程,大家可以去看看,最后列出获取IP的源程序(不涉及加载,拦截,替换的过程)
char *szwProcotol = wProcotol;
char *szRecentip=dwRecentIP;
char *szwRecentPort=wRecentPort;
char *szdwC2CIP=dwC2CIP;
char *szwC2CPort=wC2CPort;
char *szdwIP=dwIP;
char *szwPort=wPort;
bool GetDestIPInfo(DWORD ptrClassHandle,DWORD *ptrDestIp,DWORD *ptrDestPort)
{
if (ptrClassHandle==NULL || ptrDestIp==NULL || ptrDestPort==NULL) return false;
//Using Std Info Buffer
_asm
{
pushad
pushf
mov eax,ptrClassHandle
mov ecx,[eax]
mov edx,ptrDestIp
push edx
push szRecentip
push eax
mov eax,[ecx+34h]
call eax
mov eax,ptrClassHandle
mov ecx,[eax]
mov edx,ptrDestPort
push edx
push szwRecentPort
push eax
mov eax,[ecx+30h]
call eax
popf
popad
}
(*ptrDestPort) &= 0xFFFF;
if ((*ptrDestIp) != NULL && (*ptrDestPort) != NULL) return true;
_asm
{
pushad
pushf
mov eax,ptrClassHandle
mov ecx,[eax]
mov edx,ptrDestIp
push edx
push szdwC2CIP
push eax
mov eax,[ecx+34h]
call eax
mov eax,ptrClassHandle
mov ecx,[eax]
mov edx,ptrDestPort
push edx
push szwC2CPort
push eax
mov eax,[ecx+30h]
call eax
popf
popad
}
(*ptrDestPort) &= 0xFFFF;
if ((*ptrDestIp) != NULL && (*ptrDestPort) != NULL) return true;
_asm
{
pushad
pushf
mov eax,ptrClassHandle
mov ecx,[eax]
mov edx,ptrDestIp
push edx
push szdwIP
push eax
mov eax,[ecx+34h]
call eax
mov eax,ptrClassHandle
mov ecx,[eax]
mov edx,ptrDestPort
push edx
push szwPort
push eax
mov eax,[ecx+30h]
call eax
popf
popad
}
(*ptrDestPort) &= 0xFFFF;
return ((*ptrDestIp) != NULL && (*ptrDestPort) != NULL);
}
这样一个通过注入DLL方式的显IP插件就可以实现了,目前我觉得fineplus就做得很好.最后再谈一下显隐身的基本原理.以fineplus为例.
我们在反编译的过程中,注意到了这样一个函数,IQQDATA,从他的的参数来看,IQQData *,很有可能就是存放着一个用户相关信息的结构,所以开启QQ的显隐身功能原理在于QQ本身的这个部分,只要我们拦截到IQQDATA中关于本身状态的数据就可以了.QQ外挂程序Fineplus能够将该结果利用通过外挂的显隐身逻辑运算式就能将暗藏的显隐身功能开启,其实这个很简单,学过C语言选择语句的同学应该都可以写得出来.
能打开FinePlus程序内隐藏的显隐身逻辑运算格式,不过只对QQ开启后比你后隐身登录的人有效:
"('{状态}'/10-1#'[在线]':(('{IP}'==0)#'':(('{版本}'==0)#'[隐身]':'[离线]')):'[离开]':'[隐身]':'[忙碌]':'[Q我]':'[静音]':'[其他]')"
"('{状态}'/10-1#'[在线]':'[离线]':'[离开]':'[隐身]':'[忙碌]':'[Q我]':'[静音]':'[其他]')"
下面有三种能开启FinePlus隐藏的显隐身功能逻辑运算格式,请替换上面{状态}中[离线]的地方为以下逻辑运算格式即可:
(('{IP}'&&'{版本}')?'':('{版本}'?'[隐身]':'[离线]'))
('{IP}'?'':('{版本}'?'[隐身]':'[离线]'))
(('{IP}'==0)#'':(('{版本}'==0)#'[隐身]':'[离线]'))
以上逻辑运算式已经经小辉测试过是正确的。其功能就是为了判断在离线状态下,是否隐身或者离线.
到这里为止,一个可以显示IP地址和隐身与否的QQ版本就制作成功了,我再把IP数据包更新到了3月1日,再花了点时间做个安装包,手动DIY soft QQ2008贺岁版本显IP显隐身完整版本就这样做出来了.考虑版权问题,暂不提供下载.
欢迎大家阅读本教程,参考明日帝国等高手教程,表示感谢.朋友们可以与我讨论技术性细节问题.