当前位置: 首页 > news >正文

网站首页排名突然没了有没有返利网站做京东的

网站首页排名突然没了,有没有返利网站做京东的,企业网站用什么套站,网站搭建app声明#xff0c;本文章未经过疯狂绅士与runjin的同意不得转载。浅谈IPQQ软件的技术发展轨迹疯狂绅士、RunJin摘要#xff1a;本文先给出了IPQQ的界定#xff0c;并介绍了不同历史时期具有里程碑意义的IPQQ。根据几个具有里程碑意义的IPQQ#xff0c;作者简要的分析了其技术…声明本文章未经过疯狂绅士与runjin的同意不得转载。浅谈IPQQ软件的技术发展轨迹疯狂绅士、RunJin摘要本文先给出了IPQQ的界定并介绍了不同历史时期具有里程碑意义的IPQQ。根据几个具有里程碑意义的IPQQ作者简要的分析了其技术特点并以此阐述IPQQ软件的发展轨迹。关键字:   IPQQ、破解、木子QQ、外挂、珊瑚虫外挂一、IPQQ历史回顾QQ作为国内用户量最大的IM专门针对其发布一些附加功能是一个古老的话题。在QQ的弹出窗口上显示发消息用户IP的变种QQ成为大家最常用的工具,这种工具我们称为IPQQ。1999年IPQQ的始祖出现了是在QQ的前身OICQ时候出现的。邹丹制作的破解版可以说形式上开创了一个时代。尽管时间过去了好几年邹丹创立的模式几乎成为了一种标准——密界的标准以后所有QQ显IP的方式都是继承邹丹显示IP的方式。邹丹的这一举动在当时引起了一大片争议声。邹丹也收到了腾讯的律师函邹丹考虑再三后退出了为制作IPQQ的行列。 接下来又有好多个勇士站了出来其中最有名的是木子。木子的软件非常流行与邹丹的软件相比它的框架更好更稳定同时支持不同版本的QQ。木子的这个框架影响了大量的刚出道的Cracker包括本文的作者之一 ——RunJin其发布的飘云版QQ在一段时期里面被人骂成了剽窃。期间有很多显IP的QQ说白了都是参考木子的其中绝大部分根本就是木子的版本不过是改了几个字或很取巧的换上自己的标签而已。珊瑚虫前身的出现又是一个里程碑这东西由Cygwin捣腾出来的。先揭一下Cygwin的老底此人与疯狂绅士同是水木清华黑客版版主。珊瑚虫QQ外挂的原型是Cygwin大概用了两天写出来的。这东西的出现让腾讯大为挠头因为这个软件本身并没有修改QQ的任何程序。它是一个单存的外挂形式因此避免了相关的法律问题。要说明的是珊瑚虫的历史比木子更早。可以说珊瑚虫就是紧接着邹丹的版本出现的。这个时期的珊瑚虫完全由soff制作不过这个时候的珊瑚虫不是外挂形式同时质量非常高与一年后出现的木子版相比也毫不逊色。这也是后来Quaful和cygwin找到soff合作的原因。这个时期的珊瑚虫版本因为收到了腾讯的律师信而被迫中止所以给了后来木子兴起的机会。由于珊瑚虫外挂不涉及到版权问题并且其性能优越导致了珊瑚虫外挂的下载量急剧的增大从一些网站的分析来看它甚至超过了QQ本身的下载量。珊瑚虫的成功在于它不断的推出新版本作者大致统计了一下从珊瑚虫0.1版到现在的4.0beta版珊瑚虫一共推出了61个版本不包括4.0以下的测试版。正是由于珊瑚虫不懈的努力使得珊瑚虫外挂声名远扬。也许是精力的问题当珊瑚虫的第二任作者soff觉得天天追赶着QQ的新版本而被迫推出一个个新版本觉得实在是很无趣的时候内心深处对珊瑚虫来一个大变化已经变得很迫切。在外挂思维以及GAIM与Luma QQ等思想的指引下Soff考虑一种新的方式这个方式的执行者是QulfulQulful卖命的写出了珊瑚虫QQ4.0。珊瑚虫QQ4.0又是一个里程碑简单的说以前的版本只要耐心去检查QQ的内存总能找到IP地址的入口。因此可以说在珊瑚虫4.0之前的显IP的版本大都是一个简单的Cracker过程只要能看懂段刚看雪《加密与解密》一书折腾出某个IPQQ不是一见很难的事情。就是做一个外挂形式的IPQQ也并非难事。而珊瑚虫4.0可以说从根本上解决这个问题它直接截获的是QQ的网络包从网络包中获取其IP地址的。从上面的简单的回顾我们可以看出IPQQ的几个里程碑。1、邹丹IPQQ的开山鼻祖IPQQ形式的确立。2、木子IPQQ的中兴确立其成为修改QQ函数的地址方式的IPQQ的霸主地位。3、CygwinIPQQ的转折以外挂的形式击败了修改函数地址方式成为了近两年来事实上IPQQ的霸主。4、Quaful思路的拓展IPQQ也许只是珊瑚虫外挂的一个简单运用而已。上述四个里程碑中由于邹丹的版本太久远这里不作讨论本文仅就后3个里程碑简单的来分析一下其技术思路尤其是后两种。二、木子显IPQQ版本原理简介与所有的破解软件一样都有一个原则——点穴。木子与其它所有的IPQQ一样都是很偷懒的都是试图只通过修改几个字节就达到想要的效果。对于IPQQ来说能利用QQ原来的功能就利用原来的功能。这似乎是一条铁律。木子IPQQ在网上已经可以下载到它的代码。这里只讲解木子IPQQ的部分代码。SetIP proc          pushad          ;取得IP地址;          mov   eax,dword ptr [ebp-10h]          push   offset dwIp          push   offset szRecentip          push   eax          mov   ecx, [eax]          call   dword ptr [ecx34h]          ;取得端口号;……          ;取得版本号;……not2003:           下面我们再看飘云的IPQQ的代码。pushad          ; 取得IP地址;          mov   eax,dword ptr [ebp-14h]          push   offset dwIp          push   offset szRecentip          push   eax          mov   ecx,[eax]          call   dword ptr [ecx34h]          cmp   dwIp,0 ;是否已经取得IP          ……上面给出了两个不同IPQQ的如何获得IP地址部分的这两段代码是针对不同版本的QQ。黑体字表示上述的不同地方。由此我们可以看到要制作IPQQ核心是找到显示IP的那个函数的入口。这个函数的查找是个关键。而木子的出现其意义在于他给出了一个框架。因此很多后续的IPQQ就更偷懒他们只是参考木子的版本在取IP的原理上只要改动一点就可以了。木子制作的IPQQ可以说是能利用QQ的功能就尽量利用QQ的功能。而很多后来者制作的IPQQ其原则是能利用木子就尽量利用木子。上述给出的飘云的IPQQ代码就是一个例子。三、珊瑚虫4.0以下版本原理。“珊瑚虫最初版很简单的也参考了之前别人修改的方法比如版本库就是直接盗用木子的不过这个版本库盗用不是技术盗用不被人介意的。”这段话是珊瑚虫的作者Cygwin所说的。珊瑚虫外挂版本与木子版本比起来最大的不同在于——其利用了钩子的技术,不知道其是否用到了win2k的SDK包否则这段代码都可以直接参考。是在QQ运行的时候获得了其IP地址的。而不是象木子一样直接给出一个显IP的破解版本。然而,在取得IP的原理上,珊瑚虫和木子是基本相同和飘云的更是非常相象。下面是珊瑚虫3.16的取IP部分反汇编代码mov eax,dword ptr ss:[esp10]lea ecx,dword ptr ss:[esp1C]push ecxpush DUMPED.01B8D9EC     ; ASCII对应的字符为dwRecentIPmov edx,dword ptr ds:[eax]push eaxcall dword ptr ds:[edx34]………………………………………..mov eax,dword ptr ss:[esp10]lea ecx,dword ptr ss:[esp1C]push ecxpush DUMPED.01B8D9D8     ; ASCII对应的字符为dwC2CIPmov edx,dword ptr ds:[eax]push eaxcall dword ptr ds:[edx34]…………………………………..mov eax,dword ptr ss:[esp10]lea ecx,dword ptr ss:[esp1C]push ecxpush DUMPED.01B8D9C8       ; ASCII对应的字符为 dwIPmov edx,dword ptr ds:[eax]push eaxcall dword ptr ds:[edx34]虽然寄存器的具体使用不同,但动态调试的时候就会发现,其调用的函数和飘云的是一样的。珊瑚虫的原理可以用下面的话简要来表达。1、     绕开原来的流程2、     获取IP3、     把自己的窗体挂上QQ的窗体4、     把获取的IP显示在自己的窗体上RunJin用softice 、OllyDbg在: win 2000 sp4 , win 98操作系统对 QQ2005贺岁版珊瑚虫外挂进行了分析。由于win nt 平台和win9x 的差异,珊瑚虫外挂因系统的不同而分开两种工作原理。珊瑚外挂是给QQ的主程序QQ.exe外挂了一个Coralqq.dll,而完成这个工作的就是coralqq.exe .要加载一个dll文件必须是qq.exe。在win2000/xp下coralqq.exe先创建QQ的进程,同时也就创建了QQ的暂停的主线程,接着往QQ进程的内存写入代码,修改Ntdll.NtTestAlert的代码让程序跳到附加代码处执行,在执行的过程中恢复Ntdll.NtTestAlert处被改了的代码,同时加载Coralqq.dll。在win9x下,coralqq.exe先创建QQ的进程,同时也就创建了QQ的暂停的主线程,接着在QQ.exe的内存写数据,改写QQ.exe的oep从而达到改变程序流程的目的,让其先执行附加代码,加载Coralqq.dll加载完后再跳到原来的QQ.exe的oep的下一条指令继续执行。详见RunJin的珊瑚虫外挂原理分析一文。从RunJin的分析可以看出珊瑚虫外挂想得很周到的它绕开原来QQ的流程也是非常巧妙。当然如何高效的利用钩子大家可以去看相关的文章这里不再详述。可以这么说珊瑚虫最大的特色是用C代替原来木子的部分代码。而这段代码的前面部分又是那么的巧妙的绕开了原来QQ的流程。正如木子版本一样越来越多的人利用上了一个原则——能用珊瑚虫的功能就尽量利用珊瑚虫的功能。QQ狂人DIY版是把珊瑚虫外挂注入到QQ.exe里面以实现直接点QQ.exe就可以直接启动珊瑚虫外挂的目的。这类把外挂形式又变成了非外挂形式。它们所用的工具:LordPE详细的教程在网上有下载。最终出来的IPQQ部分机器可能不兼容但是大部分是可以的。四、珊瑚虫4.0 IPQQ原理简介珊瑚虫4.0可以说是IPQQ有史以来一个最重大的突破。在介绍这个版本必须提到KQL库Kwafu QQ Library。KQL是怎么出来的呢全是LumaQQ给逼的。那个如来神掌的影响力实在太大了人人都问珊瑚虫“珊瑚虫为什么不做如来神掌啊”当然在3.x的架构下是不可能的事情。后来Quaful就说干脆把LumaQQ移植过来这样就能实现了。后来Quaful用了2个月的时间完成了这个工作。Kwafu是Quaful的一个马甲的名字所以叫做Kwafu QQ Library。至于说KQL带来的QQ版本无关的其他好处都是附带的好处了。Windows平台下的KQL库重点是最大限度的保持和官方QQ客户端的兼容性所以KQL库是做为一个“外挂”来开发它的表面功能全都还是依附于官方QQ客户端来实现的。对于用户来说就是不会影响传送文件、视频聊天等功能珊瑚虫新增加的功能对原来的影响都尽可能的小。这个库很多内容是参考LumaQQ。因此Quaful把Luma等人也列为作者。在跟Quaful通过几次邮件后作者个人的看法是珊瑚虫4.0最重大的变化在于原来主要是截获内存里面的东西现在是直接截获一个个网络包。原来的方法基本上不用了解QQ的通讯协议背后的方法是要深入到QQ的协议里面去。原来的方法如果QQ重新写过一个客户端尤其是更改一下获得IP地址的函数名字等那么IPQQ基本上要重新来过一次。而采用4.0的方式基本上没有这个后顾之忧。它所需要做的是重新钩一个窗体而已因为腾讯不会不顾通讯协议的不兼容而抛弃大量的用户的。从技术思想上来说原来的方法是紧密依靠QQ现在呢是我只是依靠QQ一下而已。对于这款外挂我曾经建议过Quaful用驱动的方式来写也就是我能知道QQ的任意一个包发给谁是什么IP与端口。因为用驱动写是直接到网络的低层占用的系统资源更少但开发的工作量要增加非常的多。从工程的角度上来讲并不划算。我把这个想法告诉Quaful后他一直打击我的看法。Quaful声称“用驱动层拦截QQ包并不会比现在更省资源。无论是TDI还是NDIS对系统的影响都是全局的不仅会影响QQ还会影响所有的应用程序。这是更加消耗系统资源的做法。”作者曾试图在Win2k的DDK包中根据相关的例子来分析但发现工作巨大因此放弃。但从相关的效果上看Quaful是对的。从驱动层来写的确对系统的影响是全局的。但我认为这种写法更有扩充性。五、总结在不同时期的IPQQ中我们看到了他们之间的继承关系。如果深入到最核心的技术中去考察这个问题我们可以看到四个IPQQ可以用如下的话来概括。1、邹丹我第一个改QQ。2、木子我改QQ改出套路来了。3、Cygwin我在运行的时候改QQ。4、QuafulQQ你改吧你怎么改我都能逮住你。此外我们也可以看到其它一些作者的思路。1、     木子、珊瑚虫你能改QQ我能改你2、     木子、珊瑚虫你先改吧我学你的样改。在上述四个IPQQ中作者最欣赏珊瑚虫4.0个人认为其发展的方向非常多。当然目前的版本是通过sokect来分析的。这样做相对来说比较占内存速度也不够快。 文中涉及到如下人物作者 疯狂绅士   原水木清华黑客版版主 作者RunJin   飘云的老大 现读本科二年级邹丹78年出生木子姓名保密Cygwin姓名 保密 原水木清华黑客版版主 Soff   姓名 保密 北京理工大学当老师Quaful姓名 保密   清华大学在读博士   编写QQ外挂插件的原理和方法  前一段时间研究了下QQ目前各种外挂的机理包括著名的coralQQ。鉴于目前网上关于这方面的文章少之又少一般能找到的应该就这下面3篇(由于可能涉及版权问题我链接就不给出了  a.木子版显IPQQ的制作教程  b.关于QQ外挂DLL的加载原理的分析  c.明日帝国(sunwangme)写的我是这样来做破解qq做QQ外挂的系列  在开始我的分析前我简要对上面这些资料作下评价首先我觉得如果你也想写个类似的外挂插件他们的文章你是必看的而且特别是你想真的写出什么有用的东西的话明日帝国得文章一定要看而且必须看懂。对于木子版的教程应该说是最早“公开”的资料了很多人都是看了这个教程开始写自己的外挂的。但是他通过直接修改QQ来做显IP补丁可能引起的法律问题不说(如果你只是自娱自乐的话)他不能适应不同版本的QQ而且用户也不太能接受直接的修改而且教程已经不能直接用于目前版本的QQ了。  第二个教程是做外挂DLL插件必看的但是他丝毫没涉及显示IP的问题只是简单介绍了DLL注入的问题并对win9x环境下手动加载dll到进程空间作了分析。但是目前win9x已逐渐退出舞台所以一般只要使用CreateRemoteThread即可。  第一部分:  1.1 主流的外挂插件如何获取IP和其他信息的?  也许你会认为他拦截了底层的Socket通讯?当然不至于但这样肯定是最有效的办法。  让我们换个思路:如果你现在需要和一个QQ好友传输文件或者进行语音聊天或者发送了图片或自定义表情。那么QQ必须知道对方的IP地址和端口信息这样才能把数据传给对方。  所以很有可能QQ内部已经实现了获取IP地址和其他信息的相关函数了。的确如此。这也是木子版QQ教程里面提到的办法调用QQ内部的函数。  下面是截至QQ组件之一的CQQApplication.dll中的汇编代码:(建议先浏览木子版QQ的教程)          027832C7 8B45 F0 mov eax,dword ptr ss:[ebp-10]  027832CA 53 push ebx  027832CB 68 38558302 push CQQAppli.02835538 ; ASCII dwIP  027832D0 50 push eax  027832D1 8B08 mov ecx,dword ptr ds:[eax]  027832D3 FF51 18 call dword ptr ds:[ecx18]  027832D6 8B45 F0 mov eax,dword ptr ss:[ebp-10]  027832D9 53 push ebx  027832DA 68 40558302 push CQQAppli.02835540 ; ASCII wPort  027832DF 50 push eax  027832E0 8B08 mov ecx,dword ptr ds:[eax]  027832E2 FF51 14 call dword ptr ds:[ecx14]   CQQApplication.dll通俗来说就是负责显示和实现QQ聊天窗口的模块。就是那些和xxx聊天中的窗口所以这就是为什么要在其中寻找这样的代码的依据。  从上面的汇编来看显然是调用了2个thiscall规范的函数也就是我们所说的C类成员函数。  2个成员函数的的大致形式是this-Func(void *ptr1,char *cmd,DWORD *ptr2);其中cmd就是上面dwIP、wPort这些字符串而ptr2也很容易知道是函数返回值得存储指针。现在关键是要获取this指针也就是ecx寄存器的数据和ptr1这个神秘指针的数据。  如果你有兴趣反汇编CoralQQ中相关的代码也会发现与上面类似的调用部分。  这里暂时不深入这些函数的作用和那个cmd指针的细节我们先来研究如何获取this指针和ptr2吧。  注意  027832DF 50 push eax  027832E0 8B08 mov ecx,dword ptr ds:[eax]  这2段代码也就是说ptr2获取了那么this指针也可以得到。所以现在一切的关键就是找出ptr2的来历。这样我们就能很轻松的实现显示ip了。  1.2 神秘的ptr2指针  为了能更快的说明问题这里就不厚道的引用CoralQQ.dll的汇编了~          0056D97F 51 push ecx  0056D980 52 push edx  0056D981 50 push eax  0056D982 FF15 38AB5A00 call dword ptr ds:[5AAB38] ; BasicCtr.GetFriendQQData  0056D988 8B4424 14 mov eax,dword ptr ss:[esp14]  0056D98C 83C4 0C add esp,0C  0056D98F 3BC3 cmp eax,ebx  0056D991 0F84 03020000 je CoralQQ.0056DB9A  0056D997 57 push edi  0056D998 895C24 14 mov dword ptr ss:[esp14],ebx  0056D99C 8D5424 14 lea edx,dword ptr ss:[esp14]  0056D9A0 52 push edx  0056D9A1 68 50BB5900 push CoralQQ.0059BB50  0056D9A6 C64424 30 01 mov byte ptr ss:[esp30],1  0056D9AB 8B08 mov ecx,dword ptr ds:[eax]  0056D9AD 68 C8BA5900 push CoralQQ.0059BAC8 ; ASCII QQUSER_DYNAMIC_DATA  0056D9B2 50 push eax  0056D9B3 8B41 54 mov eax,dword ptr ds:[ecx54]  0056D9B6 FFD0 call eax  0056D9B8 8B4424 14 mov eax,dword ptr ss:[esp14]  0056D9BC 3BC3 cmp eax,ebx  0056D9BE 0F84 F9000000 je CoralQQ.0056DABD  0056D9C4 8B08 mov ecx,dword ptr ds:[eax]  0056D9C6 8D5424 1C lea edx,dword ptr ss:[esp1C]  0056D9CA 52 push edx  0056D9CB 68 ACA15900 push CoralQQ.0059A1AC ; ASCII wProcotol  0056D9D0 50 push eax  0056D9D1 8B41 30 mov eax,dword ptr ds:[ecx30]  0056D9D4 FFD0 call eax  0056D9D6 8B4424 14 mov eax,dword ptr ss:[esp14]  0056D9DA 8B08 mov ecx,dword ptr ds:[eax]  0056D9DC 8D5424 10 lea edx,dword ptr ss:[esp10]  0056D9E0 52 push edx  0056D9E1 68 94A15900 push CoralQQ.0059A194 ; ASCII dwRecentIP  0056D9E6 50 push eax  0056D9E7 8B41 34 mov eax,dword ptr ds:[ecx34]  0056D9EA FFD0 call eax  以上代码正式coralQQ 4.5版获取IP信息的片断。我们只需要关注上面的0056D982和0056D9B6地址的2个调用函数。  为什么这样说了先看下面获取dwRecentIP数据的代码它和上面提到的那个成员函数是属于一个类的(这里没提供出完整代码你可以自己验证下:-P)。那么这里的this指针从哪里来呢?  0056D9DA 8B08 mov ecx,dword ptr ds:[eax]  0056D9D6 8B4424 14 mov eax,dword ptr ss:[esp14]  按照thiscall规范ecx就保存了this指针上面代码说明ecx是来自[esp14]的我们再往上看:          0056D99C 8D5424 14 lea edx,dword ptr ss:[esp14]  0056D9A0 52 push edx  0056D9A1 68 50BB5900 push CoralQQ.0059BB50  0056D9A6 C64424 30 01 mov byte ptr ss:[esp30],1  0056D9AB 8B08 mov ecx,dword ptr ds:[eax]  0056D9AD 68 C8BA5900 push CoralQQ.0059BAC8 ; ASCII QQUSER_DYNAMIC_DATA  0056D9B2 50 push eax  0056D9B3 8B41 54 mov eax,dword ptr ds:[ecx54]  0056D9B6 FFD0 call eax  看到么0056D99C lea edx,dword ptr ss:[esp14]!!  也就是说this指针和ptr2时由这个函数获得的我们暂时以它的一个参数命名:QQUSER_DYNAMIC_DATA。  但不幸的是这个函数同样也是thiscall调用规范的也就说也是需要得到this指针……不过不慌:          0056D97F 51 push ecx  0056D980 52 push edx  0056D981 50 push eax  0056D982 FF15 38AB5A00 call dword ptr ds:[5AAB38] ; BasicCtr.GetFriendQQData  0056D988 8B4424 14 mov eax,dword ptr ss:[esp14]          0056D9AB 8B08 mov ecx,dword ptr ds:[eax]  注意上面2段代码QQUSER_DYNAMIC_DATA函数的this指针最终是[esp14]而esp14的数据是  0056D97F 51 push ecx  这段代码压入的。所幸的是GetFriendQQData是个导出函数(位于BasicCtrDll.dll)我们看看他的申明:  int GetFriendQQData(struct IQQCore *,unsigned long,struct IQQData * *);  上面这个push ecx实际上是压入了参数struct IQQData * *。  所以现在的只要获得struct IQQCore *,和第二个神秘参数的含义就能实现显示IP的功能了。1.3 IQQCore和Uin  int GetFriendQQData(struct IQQCore *,unsigned long,struct IQQData * *);  这个函数从而获得那个struct IQQData *指针。但问题就是要调用这个函数必须要提供2个参数:IQQCore *和一个unsigned long(DWORD)的神秘数据。  在开始正式分析前请各位思考下如果要你编写一个能显示好友IP的函数你需要先知道什么呢?  至少需要知道要去获取哪个QQ好友吧。这个肯定是必须的否则函数就没有执行的意义了  现在我们跟踪下上面这个GetFriendQQData函数。在其入口点下断点。然后小心的把鼠标移动到QQ好友列表中某个头像上(需要使用CoralQQ……有点不厚道)。这时候应该程序就会被断下。  因为正常理鼠标移至好友头像会显示信息卡片CoralQQ会在下面显示IP信息所以按照上一篇文章反汇编的代码GetFriendQQData必然会调用。我们从堆栈里面找到这个unsigned long对应的数据:  0x1A53836  因为是DWORD数据把它转化为10进制看看:27605046  这不是我的QQ号码么……的确先前鼠标是移动在我的头像上了。  所以可以猜测这个unsigned long就是好友的QQ号码。  经过多次验证的确如此。  所以这个神秘的unsigned long明确:他是要获取好友信息的号码,顺便补充下这个unsigned long在QQ中可是有专门名字的:Uin  接下来就是struct IQQCore*我想他的作用从名字中应该就能猜出大概来。虽然具体他的结构我还没弄清但可以肯定他好比是QQ程序内核信息的指针。而现在最关键的问题是如何去获得它。  如果你研究过BasicCtrlDll.dll中导出的函数你会发现几乎一半的函数的参数都由这个IQQCore比如:          int GetCurrentStatus(struct IQQCore *,int *)  int GetCurrentUin(struct IQQCore *,unsigned long *)  int GetFriendStat(struct IQQCore *,unsigned long)  那么我们就拦截其中的一部分函数看看提供给他们的这个struct IQQCore *参数具体是什么。  如果你的确这样做了那么会发现所有的函数无论在什么时候这个struct IQQCore *的值是确定的唯一的。如果你这个IQQCore *指针的地址区域下内存写入断点的话会发现struct IQQCore *实际上在QQ进行登录初始化时就创建了以后就不再被修改。  所以现在的问题就很简单了我们可以暂时不用理会struct IQQCore *到底是什么只要能获取到他就ok  1.4 如何获取struct IQQCore *?  如果只是调试个QQ得到struct IQQCore *是非常容易的但记住我们是要编写外挂。所以就是说我们要问:外挂如果通过程序来获取这个指针呢?  最野蛮的办法:把外挂写成一个调试器模拟手工调试的过程获得这个IQQCore *。ok我很佩服你这样做这也是我原先的想法。虽然写这个一个调试器是很简单的但是他基本上没有实际意义因为不能应对各种版本的QQ程序而且也就无法再使用OD这些调试器来调试你的程序了  下面的方法要感谢明日帝国(sunwangme)写的教程了可能一开始你看他教程会不知所云但相信你现在去看他的文章就会很有感触。  上面说过这个IQQCore 是不会改变的而且BasicCtrlDll.dll导出的那么多函数又偏偏要用到他为什么不去拦截一个有IQQCore *参数的函数来获取这个IQQCore *呢?  具体的做法我会在编写插件时说明。可能你会想拦截导出函数(也就是API)不也是调试器作的事么?其实也有别的办法这里就是用API Hook技术来实现的(建议先了解下win32的hook技术)。  问题是API SetWindowsHookEx是不可能hook一个API的。所以这里要用比较“底层”的办法:  一个导出函数的入口内存地址可以用GetProcAddress API获取我们只要修改程序的代码使得他在原先函数入口点执行时跳入我们的函数取执行然后再跳转回来即可。(实际做法不是这样在说明如何编写插件时我会说到)  现在问题就是要在BasicCtrlDll.dll导出函数中选取一个比较理想的函数取拦截得到IQQCore  要拦截的函数应该具有如下特点:  函数形参简单最好只有IQQCore *一个参数  函数能尽早被调用这样能及早的获取IQQCore *  函数不能是thiscall规范的也就是说函数必须是全局函数不是一个成员函数  为何要这些特点应该都能理解我对最后一个做下说明thiscall规范的函数还需要一个类的this指针地址这会给拦截造成一定麻烦(今后就会遇到这样的情况以后再讨论)。  最终我们选取的函数是QQHelperDll.dll中的一个导出函数:  int IsLogin(struct IQQCore *);  很满足我们的要求而且用OD跟踪发现他在QQ登录后就不停的调用太爽了……  总结一下:要获取struct IQQCore *通过拦截API获取参数实现我们拦截的函数选用了IsLogin()。  1.5 Uin和struct IQQData *  现在还有2个问题要去研究第一在调用GetFriendQQData时候Uin(就是那个unsigned long参数)如何确定呢?  这个问题要等到我介绍插件编写时在讨论但可以先做下暗示我们编写的插件是需要在打开和好友聊天的对话框以及将鼠标移动到好友头像上时显示对方的IP信息就第一个情况:QQ的聊天对话框里面不就有好友的QQ号码(Uin)么?第二个情况:虽然探出的信息卡片没有号码但可以猜测QQ也是先需要获取相关信息的。  现在我们再说说这个IQQData *的作用看看BasicCtrlDll.dll的一些导出函数:          long GetQQDataBuf(struct IQQData *,char const *,class CString )  long GetQQDataStr(struct IQQData *,char const *,class CString )  其中需要IQQData *参数那么我们看看这些函数有什么作用呢?以GetQQDataStr在CoralQQ中的使用情况为例:          0056DAC4 57 push edi  0056DAC5 68 DCBA5900 push CoralQQ.0059BADC ; ASCII NAME  0056DACA 52 push edx  0056DACB FF15 44AB5A00 call dword ptr ds:[5AAB44] ; BasicCtr.GetQQDataStr  0056DAE5 8B4424 24 mov eax,dword ptr ss:[esp24]  0056DAE9 8D56 34 lea edx,dword ptr ds:[esi34]  0056DAEC 52 push edx  0056DAED 68 ECBA5900 push CoralQQ.0059BAEC ; ASCII REMARK_REALNAME  0056DAF2 50 push eax  0056DAF3 FF15 44AB5A00 call dword ptr ds:[5AAB44] ; BasicCtr.GetQQDataStr  0056DAF9 8B5424 30 mov edx,dword ptr ss:[esp30]  0056DAFD 8D4E 38 lea ecx,dword ptr ds:[esi38]  0056DB00 51 push ecx  0056DB01 68 FCBA5900 push CoralQQ.0059BAFC ; ASCII COUNTRY  0056DB06 52 push edx  0056DB07 FF15 44AB5A00 call dword ptr ds:[5AAB44] ; BasicCtr.GetQQDataStr  0056DB0D 8B4C24 3C mov ecx,dword ptr ss:[esp3C]  0056DB11 8D46 3C lea eax,dword ptr ds:[esi3C]  0056DB14 50 push eax  0056DB15 68 04BB5900 push CoralQQ.0059BB04 ; ASCII PROVINCE  0056DB1A 51 push ecx  0056DB1B FF15 44AB5A00 call dword ptr ds:[5AAB44] ; BasicCtr.GetQQDataStr  这些代码是在获取IP信息后出现的猜猜在做什么呢?NAMECOUNTRYPROVINCE这些词汇来看应该是在获取当前要显示ip好友的名字、国籍、省份。而具体的执行函数就是GetQQDataStr。  再结合这个函数的参数来看IQQData *,很有可能就是存放着一个用户相关信息的结构  事实也是如此的到目前为止编写QQ外挂插件的条件已经具备。 2.编写QQ显IP插件  2.1 编写加载外挂dll的程序  这里采用VC作为开发环境我使用的是VS2005  首先说下大体的思路:  这里仿造coralQQ一样将真正的外挂代码写入dll然后编写一个exe文件去加载qq.exe并把我们写得dll注入。  这一步在前一篇文章中已经给出了具体代码。  2.2 编写插件主体  感觉自己如果一涉及具体代码就回说不来话所以这次就先谈思路然后给出部分代码。  dll要做的事:  将我们前面分析过的关键API挂钩以便得到IQQCore *Uin以及在qq聊天窗口弹出时进行捕获以便显示IP信息。  要做到上面的要求首先就是要在dll加载后开始做API hook的工作。  不过这件事情不能在DllMain里面写推荐的做法是在DllMain里面创建一个新的线程线程的执行函数我们设为:WorkerProc(VC编写的话推荐用_beginthread创建这个线程否则无法使用CRT函数)为什么不能直接在DllMain里面写我稍候分析  然后就是在WorkerProc里面写入具体的hook代码。  1.拦截QQHelperDll.dll中的IsLogin函数  前面分析过了IQQCore *指针可以通过拦截这个API来获取。  这里我们采用的是《windows核心编程》中推荐的拦截API hook的办法(修改入口地址跳转相对他烦了些而且我们这里只是想做hook):通过动态修改API调用者模块的IAT表将原先API的入口地址替换成我们函数的。具体的替换代码我们就采用书中提供的了的ReplaceIATEntryInOneMod(见前一篇)。  现在要注意一个问题我们用来替换原先API的函数必须和原函数采用同样的调用规范这个IsLogin本身就是cdecl得所以只要用个形参和返回值一样的函数取替换即可:  给出实现本功能的代码:          typedef int (*OrgIsLogin)(DWORD ptrIQQCore);  int PokeIsLogin(DWORD ptrIQQCore)  {   global_ptrIQQCore ptrIQQCore;   return ((OrgIsLogin)(PROC)OrgIsLoginProc)(ptrIQQCore);  }  下面代码在WorkerProc函数中///  OrgIsLoginProc GetProcAddress( GetModuleHandleA(QQHelperDll.dll),?IsLoginYAHPAUIQQCoreZ);  if (ReplaceIATEntryInOneMod(QQHelperDll.dll,OrgIsLoginProc,(PROC)PokeIsLogin,GetModuleHandleA(qq.exe)))  {   //替换成功  }  //  今后只要QQ.exe调用IsLogin我们的PokeIsLogin函数就会调用并把IQQCore纪录下来注意替换的函数要最后去调用原函数否则就会让程序崩溃。  2.拦截SetForegroundWindow API  拦截该API是因为每次弹出新的QQ聊天窗口时CQQApplication.dll都会去调用它以便把聊天窗口至于前景显示。所以拦截CQQApplication.dll对他的调用就能在由新的聊天窗口出现时调用我们插件的代码去显示IP信息而不必傻傻的去写循环等待了  这里就要注意SetForegroundWindow 是采用stdall调用规范的所以别忘在替换函数名前加上__stdcall(或WINAPI宏)标记。  该部分的替换代码如下:          typedef BOOL ( __stdcall *OrgSetForegrandWindow)(HWND hWnd);  extern C BOOL APIENTRY OnQQWndShow(HWND hWnd)  {   bool trueResult ((OrgSetForegrandWindow)(PROC)OrgFuncProc)(hWnd);   return trueResult;  }  //下面代码在WorkerProc函数或由其调用的函数中  OrgFuncProc GetProcAddress( GetModuleHandleA(user32),SetForegroundWindow);  if (ReplaceIATEntryInOneMod(user32.dll,OrgFuncProc,(PROC)OnQQWndShow,global_hCQQAppModule))  {   //替换函数入口成功  }  其中global_hCQQAppModule是CQQApplication.dll在qq.exe中的模块句柄可以调用GetModuleHandleA(CQQApplication.dll)来实现。不过现在存在一个问题  用od加载qq.exe就会发现实际上CQQApplication.dll并不是在qq.exe启动后加载的而是在登录以后。所以如果我们的dll插件在被加载之后立刻调用GetModuleHandleA的话就会返回NULL那么之后的函数替换就不可能实现了。  这里我用了个比较笨的办法在替换SetForegroundWindow前编写循环不断的去掉用GetModuleHandleA直到返回非null而为了防止频率过快可以在循环中加上Sleep函数。(之前也尝试loadlibrary提前加载但一直失败。还有中办法就是从前面的IsLogin来判断是否登录了QQ。但没有试验过。总之如果你有比较好的办法也希望告诉我)  这部分的代码如下:          bool WaitforLogon()  {   while(!bIsDllUnload)   {    global_hCQQAppModule GetModuleHandleA(CQQApplication.dll);    if (global_hCQQAppModule) return true;    Sleep(300);   }   return false;  }  这就是为什么前面说过不能再dllmain里面作函数替换的工作了否则会导致dllmain无法退出从而会锁死整个qq 3.获取Uin  现在IQQCore *已经获得了同时只要在OnQQWndShow中写入得到用户IP信息的代码再使用FindWindow的方法把原先的广告去除再创建个Edit或者Static来显示我们的数据即可。  但之前还要得到Uin也就是对方好友的QQ号。  其实这里有个很笨的办法:QQ聊天对话框中有对方的号码的:比如“heaven(27605046)(后面是个性签名)。的确可以用FindWindowGetWindowText获取然后得到括号里面的数据就好了但是是否有更简单办法呢?有  这里要感谢明日帝国(sunwangme)的教程这里就是用他的方法了具体原理还是大家去他blog看吧(google一下)  大体的方法是:在QQ准备显示聊天对话框时上面“heaven(27605046)(后面是个性签名)这段文字会调用位于QQBaseClassInDll.dll中的CAllInOneStatusBar::SetUin(unsigned long);这个函数其中参数就是我们要的QQ号了。而且可以保证CQQApplication.dll仅仅在要显示对话框前才会调用它。(再次感谢明日帝国)  所以和上面一样这次拦截CAllInOneStatusBar::SetUin(unsigned long);          OrgSetUINProc   GetProcAddress(GetModuleHandleA(QQBaseClassInDll.dll),?SetUinCAllInOneStatusBarQAEX_JZ);  if (ReplaceIATEntryInOneMod(QQBaseClassInDll.dll,OrgSetUINProc,(PROC)Poke_GETUIDA,global_hCQQAllInOne)){  }  今后就会先调用我们的OrgSetUINProc其中获取参数即可。  不过要注意2个问题第一这个QQBaseClassInDll.dll也不是一开始加载更不是在登录后加载而是在第一次要显示QQ聊天窗口才加载不过比较幸运的是可以直接LoadLibrary把它先载过来。  还有一个问题就是SetUin是thiscall规范的……哎自己对thiscall还不是很了解所以怕出错那个OrgSetUINProc只能用naked调用规范了同时要自己写汇编去完成细节的事:          __declspec( naked ) int Poke_GETUIDA()  {   _asm   {    push ecx    mov ecx,[esp8]    mov dwRecentUINA,ecx    pop ecx    jmp OrgSetUINProc   }  }  ok这样一切都完成了  3.编写获取IP信息的代码  先整理下上面我们3个替换函数的执行顺序:  PokeIsLogin:最好执行且今后不断被调用  Poke_GETUIDA:在将要显示QQ聊天窗口时执行  OnQQWndShow:在Poke_GETUIDA之后运行。  所以可以保证在OnQQWndShow中可以得到我们获取IP信息所有必要的参数了。  那么就开始编写获取IP的代码:  按照前面分析的先用BasicCtr.GetFriendQQData得到当前好友的IQQData *:          DWORD MainHandle;  if (ptrBasicCtr_GetFriendQQDataNULL || global_ptrIQQCoreNULL) return 0;  _asm  {   mov edx,dwID   mov eax,global_ptrIQQCore   lea ecx,MainHandle   push ecx   push edx   push eax   call ptrBasicCtr_GetFriendQQData ; BasicCtr.GetFriendQQData   add esp,0xC  }  其中dwID是Uin即用DWORD保存的QQ号码  global_ptrIQQCore就是前面获得的IQQCore *  ptrBasicCtr_GetFriendQQData 是GetFriendQQData的入口地址用GetProcAddress得到  最终MainHandle将保存IQQData *如果运行失败会返回null  接下来就是通过QQUSER_DYNAMIC_DATA(暂时命名)函数来得到动态信息类的指针:          char *szQQUSER_DYNAMIC_DATA QQUSER_DYNAMIC_DATA;  DWORD tmpInfo;  DWORD returnVal;  tmpInfo 0xba863a1e;  if (mainHandle NULL)  {   return NULL;  }  _asm  {   mov eax,mainHandle   lea edx,returnVal   push edx   lea edx,tmpInfo   push edx   mov ecx,[eax]   push szQQUSER_DYNAMIC_DATA   push eax   call [ecx54h]  }  结果将保存在returnVal中同样如果执行错误returnValNULL  最后就是去获取IP地址了          char *szwProcotol wProcotol;  char *szRecentipdwRecentIP;  char *szwRecentPortwRecentPort;  char *szdwC2CIPdwC2CIP;  char *szwC2CPortwC2CPort;  char *szdwIPdwIP;  char *szwPortwPort;  bool GetDestIPInfo(DWORD ptrClassHandle,DWORD *ptrDestIp,DWORD *ptrDestPort)  {   if (ptrClassHandleNULL || ptrDestIpNULL || ptrDestPortNULL) 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,[ecx34h]    call eax    mov eax,ptrClassHandle    mov ecx,[eax]    mov edx,ptrDestPort    push edx    push szwRecentPort    push eax    mov eax,[ecx30h]    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,[ecx34h]    call eax    mov eax,ptrClassHandle    mov ecx,[eax]    mov edx,ptrDestPort    push edx    push szwC2CPort    push eax    mov eax,[ecx30h]    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,[ecx34h]    call eax    mov eax,ptrClassHandle    mov ecx,[eax]    mov edx,ptrDestPort    push edx    push szwPort    push eax    mov eax,[ecx30h]    call eax    popf    popad   }   (*ptrDestPort) 0xFFFF;   return ((*ptrDestIp) ! NULL (*ptrDestPort) ! NULL);  }  ptrClassHandle是前面得到的returnValIP地址的DWORD数据和WORD的port信息将保存在后2个参数指针的地址中。(代码借鉴了CoralQQ)  到目前为止已大功告成!其他的细节代码就请各位发挥吧  4.扩展  上面并没有介绍如何得到对方QQ版本的信息其实和获取IP一样你在CQQApplication.dll中找到wProcotol的字符串参考就会发现它和获取IP的代码很像直接抄下来用就是了。            再分享一下我老师大神的人工智能教程吧。零基础通俗易懂风趣幽默还带黄段子希望你也加入到我们人工智能的队伍中来https://blog.csdn.net/jiangjunshow
http://www.zqtcl.cn/news/61346/

相关文章:

  • 深圳网站制作公司地址如何用dw做网站地图
  • 竞价推广是什么工作佛山seo优化排名推广
  • 网站页面设置手机版长沙好的网站建设品牌
  • 学校教育网站模板华强北做电子网站
  • 网站 模板 下载精准营销的营销方式
  • 阳光家园广州网站深圳创业园
  • 解决方案的网站建设好的专题网站
  • 查网站域名备案查询企业网站开发与设计论文
  • 券商 做网站动漫与游戏制作专业有前途吗
  • 电信改公网ip可以做网站吗优惠券推广网站怎么做
  • 慈溪建设网站wordpress伪静态301
  • 嘉兴市城乡规划建设管理网站权重提升
  • 网站美工培训课程深圳物流公司查询大全
  • 企业在线设计网站wordpress描述插件
  • 网站开发设计思路网站商城建设哪家好
  • 苏宁电器网站建设特点分析微商城开发价格
  • 高端品牌网站建设策划方案一个公司可以做几个百度推广
  • 舟山企业网站建设公司优化设计五年级下册语文答案
  • 软件公司网站模板wordpress邮箱修改
  • 外销网站怎么做的做网站一个月工资
  • 河北廊坊做网站山西网络公司网站建设
  • 怎么样做淘宝优惠券网站常州企业自助建站系统
  • 百度的网站关键词被篡改昆明网站开发建
  • 网站开发界面深圳小蚁人网站建设
  • 网站建设 考题建站做得好的公司
  • 专业零基础网站建设教学在哪里空包自己可以做物流信息的网站
  • 深圳做网页的网站宝塔wordpress ssl证书
  • 浙江网站建设品牌设计百度不收录网站关键词
  • 上海医院网站建设成都it培训机构
  • 做网站应该用什么配置的电脑html官方网站