Programming 板


游戏外挂指南 http://delphi.ktop.com.tw/board.php?cid=30&fid=75&tid=64920 ) 游戏外挂指南 http://www.donews.net/eb/archive/2004/07/09/39944.aspx 要想在修改游戏中做到百战百胜,是需要相当丰富的电脑知识的。 有很多电脑高手就是从玩游戏,修改游戏中,逐步对电脑产生浓厚的兴趣,逐步成长起来的。 不要在羡慕别人能够做到的,因为别人能够做的你也能够!我相信你们看了本教 程後,会对游戏有一个全新的认识,呵呵,因为我是个好老师! (别拿鸡蛋砸我呀,救命啊!#¥%……*) 不过要想从修改游戏中学到知识, 增加自己的电脑水准,可不能只是靠修改游戏呀!要知道,修改游戏只是一个验 证你对你所了解的某些电脑知识的理解程度的场所,只能给你一些发现问题、 解决问题的机会,只能起到帮助你提高学习电脑的兴趣的作用,而决不是学习电脑的捷径。 一:什麽叫外挂?   现在的网路游戏多是基於Internet上客户/伺服器模式,服务端程式运行在 游戏伺服器上,游戏的设计者在其中创造一个庞大的游戏空间,各地的玩家可以 通过运行用户端程式同时登录到游戏中。 简单地说,网路游戏实际上就是由游戏开发商提供一个游戏环境,而玩家们就是在这个环境中相对自由和开放地进行游戏操作。 那麽既然在网路游戏中有了伺服器这个概念,我们以前传统的修改游戏方法就显 得无能为力了。记得我们在单机版的游戏中,随心所欲地通过记忆体搜索来修改 角色的各种属性,这在网路游戏中就没有任何用处了。 因为我们在网路游戏中所扮演角色的各种属性及各种重要资料都存放在伺服器 上,在我们自己机器上(用户端)只是显示角色的状态,所以通过修改用户端记 忆体里有关角色的各种属性是不切实际的。 那麽是否我们就没有办法在网路游戏中达到我们修改的目的?回答是"否"。   我们知道Internet客户/伺服器模式的通讯一般采用TCP/IP通信协定, 资料交换是通过IP资料包的传输来实现的,一般来说我们用户端向伺服器发出 某些请求,比如移动、战斗等指令都是通过封包的形式和伺服器交换资料。 那麽我们把本地发出消息称为SEND,意思就是发送资料,伺服器收到我们SEND 的消息後,会按照既定的程式把有关的资讯回馈给用户端,比如,移动的座标, 战斗的类型。那麽我们把用户端收到伺服器发来的有关消息称为RECV。 知道了这个道理,接下来我们要做的工作就是分析用户端和伺服器之间往来的资 料(也就是封包),这样我们就可以提取到对我们有用的资料进行修改,然後类 比伺服器发给用户端,或者模拟用户端发送给伺服器,这样就可以实现我们修改 游戏的目的了。   目前除了修改游戏封包来实现修改游戏的目的,我们也可以修改用户端的有 关程式来达到我们的要求。我们知道目前各个伺服器的运算能力是有限的, 特别在游戏中,游戏伺服器要计算游戏中所有玩家的状况几乎是不可能的, 所以有一些运算还是要依靠我们用户端来完成,这样又给了我们修改游戏提供了 一些便利。比如我们可以通过将用户端程式脱壳来发现一些程式的判断分支, 通过跟踪调试我们可以把一些对我们不利的判断去掉,以此来满足我们修改游戏 的需求。 在下几个章节中,我们将给大家讲述封包的概念,和修改跟踪用户端 的有关知识。大家准备好了吗?      游戏资料格式和存储:   在进行我们的工作之前,我们需要掌握一些关於电脑中储存资料方式的知识 和游戏中储存资料的特点。本章节是提供给菜鸟级的玩家看的,如果你是高手就 可以跳过了,如果,你想成为无坚不摧的剑客,那麽,这些东西就会花掉你一些 时间;如果,你只想作个江湖的游客的话,那麽这些东西,了解与否无关紧要。 是作剑客,还是作游客,你选择吧!   现在我们开始!首先,你要知道游戏中储存资料的几种格式, 这几种格式是:位元组(BYTE)、字(WORD)和双字(DOUBLE WORD), 或者说是8位、16位元和32位元储存方式。位元组也就是8位元方式能储存0~255的数位; 字或说是16位元储存方式能储存0~65535的数;双字即32位元方式能储存0~4294967295的数。   为何要了解这些知识呢?在游戏中各种参数的最大值是不同的,有些可能 100左右就够了,比如,金庸群侠传中的角色的等级、随机遇敌个数等等。 而有些却需要大於255甚至大於65535,象金庸群侠传中角色的金钱值可达到数百万。 所以,在游戏中各种不同的资料的类型是不一样的。在我们修改游戏时需要寻找 准备修改的资料的封包,在这种时候,正确判断资料的类型是迅速找到正确位址的重要条件。   在电脑中资料以位元组为基本的储存单位,每个位元组被赋予一个编号, 以确定各自的位置。 这个编号我们就称为位址。 在需要用到字或双字时,电脑用连续的两个位元组 来组成一个字,连续的两个字组成一个双字。 而一个字或双字的位址就是它们的低位元位元组的位址。 现在我们常用的Windows 9x作业系统中,位址是用一个32位的二进位数字表示的。 而在平时我们用到记忆体位址时,总是用一个8位的16进制数来表示它。      二进位和十六进位又是怎样一回事呢?   简单说来,二进位数字就是一种只有0和1两个数码,每满2则进一位的计数进位法。 同样,16进制就是每满十六就进一位的计数进位法。 16进制有0--F十六个数位,它为表示十到十五的数位采用了A、B、C、D、E、F六个数位, 它们和十进位的对应关系是:A对应於10,B对应於11,C对应於12,D对应 於13,E对应於14,F对应於15。而且,16进制数和二进位数字间有一个简单 的对应关系,那就是;四位二进位数字相当於一位16进制数。比如,一个四位 的二进位数字1111就相当於16进制的F,1010就相当於A。   了解这些基础知识对修改游戏有着很大的帮助,下面我就要谈到这个问题。 由於在电脑中资料是以二进位的方式储存的,同时16进制数和二进位间的转换 关系十分简单,所以大部分的修改工具在显示电脑中的资料时会显示16进制的 代码,而且在你修改时也需要输入16进制的数位。你清楚了吧?   在游戏中看到的资料可都是十进位的,在要寻找并修改参数的值时, 可以使用Windows提供的计算器来进行十进位和16进制的换算, 我们可以在开始功能表里的程式组中的附件中找到它。 现在要了解的知识也差不多了!不过,有个问题在游戏修改中是需要注意的。 在电脑中资料的储存方式一般是低位元数储存在低位元位元组,高位数储存在高 位位元组。比如,十进位数字41715转换为16进制的数为A2F3,但在电脑中这个数被存为F3A2。   看了以上内容大家对资料的存贮和资料的对应关系都了解了吗? 好了,接下来我们要告诉大家在游戏中,封包到底是怎麽一回事了,来!大家把袖口卷起来,让我们来干活吧!   二:什麽是封包?   怎麽截获一个游戏的封包?怎麽去检查游戏伺服器的ip地址和埠号? Internet用户使用的各种资讯服务,其通讯的资讯最终均可以归结 为以IP包为单位的资讯传送,IP包除了包括要传送的资料资讯外, 还包含有资讯要发送到的目的IP位址、资讯发送的源IP位址、以及一些相关的控制资讯。 当一台路由器收到一个IP资料包时,它将根据资料包中的目的IP位址项查找路由表,根据查找的结果将此IP资料包送往对应埠。 下一台IP路由器收到此资料包後继续转发,直至发到目的地。 路由器之间可以通过路由协定来进行路由资讯的交换,从而更新路由表。 那麽我们所关心的内容只是IP包中的资料资讯,我们可以使用许多监听网路的 工具来截获用户端与伺服器之间的交换资料,下面就向你介绍其中的一种工具: WPE。 WPE使用方法:执行WPE会有下列几项功能可选择: SELECT GAME选择目前在记忆体中您想拦截的程式, 您只需双击该程式名称即可。 TRACE追踪功能。用来追踪撷取程式送收的封包。 WPE必须先完成点选欲追踪的程式名称,才可以使用此项目。 按下Play键开始撷取程式收送的封包。您可以随时按下 | | 暂停追踪,想继续时 请再按下 | | 。按下正方形可以停止撷取封包并且显示所有已撷取封包内容。 若您没按下正方形停止键,追踪的动作将依照OPTION里的设定值自动停止。 如果您没有撷取到资料,试试将OPTION里调整为Winsock Version 2。 WPE 及 Trainers 是设定在显示至少16 bits 颜色下才可执行。 FILTER过滤功能。用来分析所撷取到的封包,并且予以修改。 SEND PACKET送出封包功能。能够让您送出假造的封包。 TRAINER MAKER制作修改器。 OPTIONS设定功能。让您调整WPE的一些设定值。 FILTER的详细教学 - 当FILTER在启动状态时 ,ON的按钮会呈现红色。- 当您启动FILTER时,您随时可以关闭这个视窗。 FILTER将会保留在原来的状态,直到您再按一次 on / off 钮。 - 只有FILTER启用钮在OFF的状态下,才可以勾选Filter前的方框来编辑修改。 - 当您想编辑某个Filter,只要双击该Filter的名字即可。 NORMAL MODE: 范例: 当您在 Street Fighter Online ﹝快打旋风线上版﹞游戏中,您使用了两次火球而且击中了对方, 这时您会撷取到以下的封包: SEND-> 0000 08 14 21 06 01 04 SEND-> 0000 02 09 87 00 67 FF A4 AA 11 22 00 00 00 00 SEND-> 0000 03 84 11 09 11 09 SEND-> 0000 0A 09 C1 10 00 00 FF 52 44 SEND-> 0000 0A 09 C1 10 00 00 66 52 44   您的第一个火球让对方减了16滴﹝16 = 10h﹞的生命值, 而您观察到第4跟第5个封包的位置4有10h的值出现,应该就是这里了。   您观察10h前的0A 09 C1在两个封包中都没改变, 可见得这3个数值是发出火球的关键。   因此您将0A 09 C1 10填在搜寻列﹝SEARCH﹞,然後在修改列﹝MODIFY﹞的位置4填上FF。 如此一来,当您再度发出火球时,FF会取代之前的10,也就是攻击力为255的火球了! ADVANCED MODE: 范例:   当您在一个游戏中,您不想要用真实姓名,您想用修改过的假名传送给对方。 在您使用TRACE後,您会发现有些封包里面有您的名字出现。 假设您的名字是Shadow,换算成16进位则是﹝53 68 61 64 6F 77﹞; 而您打算用moon﹝6D 6F 6F 6E 20 20﹞来取代他。 SEND-> 0000 08 14 21 06 01 04  SEND-> 0000 01 06 99 53 68 61 64 6F 77 00 01 05   SEND-> 0000 03 84 11 09 11 09  SEND-> 0000 0A 09 C1 10 00 53 68 61 64 6F 77 00 11   SEND-> 0000 0A 09 C1 10 00 00 66 52 44   但是您仔细看,您的名字在每个封包中并不是出现在相同的位置上 – 在第2个封包里,名字是出现在第4个位置上- 在第4个封包里, 名字是出现在第6个位置上 在这种情况下, 您就需要使用ADVANCED MODE- 您在搜寻列﹝SEARCH﹞填上:53 68 61 64 6F 77 ﹝请务必从位置1开始填﹞- 您想要从原来名字Shadow的第一个字母开始置换新名字, 因此您要选择从数值被发现的位置开始替代连续数值 ﹝from the position of the chain found﹞。- 现在,在修改列﹝MODIFY﹞000的位置填上:6D 6F 6F 6E 20 20 ﹝此为相对应位置,也就是从原来搜寻栏的+001位置开始递换﹞- 如果您想从封包的第一个位置就修改数值, 请选择﹝from the beginning of the packet﹞   了解一点TCP/IP协议常识的人都知道,互联网是将资讯资料打包之後再传送出去的。 每个资料包分为头部资讯和资料资讯两部分。 头部资讯包括资料包的发送位址和到达位址等。 资料资讯包括我们在游戏中相关操作的各项资讯。 那麽在做截获封包的过程之前我们先要知道游戏伺服器的IP位址 和埠号等各种资讯,实际上最简单的是看看我们游戏目录下, 是否有一个SERVER.INI的配置档,这个档里你可以查看到个游戏伺服器 的IP位址,比如金庸群侠传就是如此, 那麽除了这个我们还可以在DOS下使用NETSTAT这个命令,   NETSTAT命令的功能是显示网路连接、路由表和网路介面资讯, 可以让用户得知目前都有哪些网路连接正在运作。 或者你可以使用木马客星等工具来查看网路连接。工具是很多的, 看你喜欢用哪一种了。   NETSTAT命令的一般格式为:NETSTAT [选项]   命令中各选项的含义如下:-a 显示所有socket,包括正在监听的。 -c 每隔1秒就重新显示一遍,直到用户中断它。-i 显示所有网路介面的资讯。 -n 以网路IP位址代替名称,显示出网路连接情形。 -r 显示核心路由表,格式同"route -e"。-t 显示TCP协定的连接情况。-u 显示UDP协定的连接情况。 -v 显示正在进行的工作。   三:怎麽来分析我们截获的封包?   首先我们将WPE截获的封包保存为文字档案,然後打开它, 这时会看到如下的资料 (这里我们以金庸群侠传里PK店小二用户端发送的资料为例来讲解): 第一个文件:SEND-> 0000 E6 56 0D 22 7E 6B E4 17 13 13 12 13 12 13 67 1B SEND-> 0010 17 12 DD 34 12 12 12 12 17 12 0E 12 12 12 9B SEND-> 0000 E6 56 1E F1 29 06 17 12 3B 0E 17 1A SEND-> 0000 E6 56 1B C0 68 12 12 12 5A SEND-> 0000 E6 56 02 C8 13 C9 7E 6B E4 17 10 35 27 13 12 12 SEND-> 0000 E6 56 17 C9 12 第二个档: SEND-> 0000 83 33 68 47 1B 0E 81 72 76 76 77 76 77 76 02 7E SEND-> 0010 72 77 07 1C 77 77 77 77 72 77 72 77 77 77 6D SEND-> 0000 83 33 7B 94 4C 63 72 77 5E 6B 72 F3 SEND-> 0000 83 33 7E A5 21 77 77 77 3F SEND-> 0000 83 33 67 AD 76 CF 1B 0E 81 72 75 50 42 76 77 77 SEND-> 0000 83 33 72 AC 77   我们发现两次PK店小二的资料格式一样,但是内容却不相同, 我们是PK的同一个NPC,为什麽会不同呢? 原来金庸群侠传的封包是经过了加密运算才在网路上传输的, 那麽我们面临的问题就是如何将密文解密成明文再分析了。   因为一般的资料包加密都是异或运算,所以这里先讲一下什麽是异或。 简单的说,异或就是"相同为0,不同为1"(这是针对二进位按位元来讲的), 举个例子,0001和0010异或,我们按位对比,得到异或结果是0011, 计算的方法是:0001的第4位为0,0010的第4位为0,它们相同, 则异或结果的第4位按照"相同为0,不同为1"的原则得到 0,0001的第3位为0,0010的第3位为0, 则异或结果的第3位得到0,0001的第2位为0,0010的第2位为1, 则异或结果的第2位得到1,0001的第1位为1,0010的第1位为0, 则异或结果的第1位元得到1,组合起来就是0011。 异或运算今後会遇到很多,大家可以先熟悉熟悉,熟练了对分析很有帮助的。 下面我们继续看看上面的两个档,按照常理,资料包的资料不会全部都有值的, 游戏开发时会预留一些位元组空间来便於日後的扩充,也就是说资料包里会存在 一些"00"的位元组,观察上面的档,我们会发现档一里很多"12",档二里很多 "77",那麽这是不是代表我们说的"00"呢?推理到这里,我们就开始行动吧!   我们把档一与"12"异或,档二与"77"异或,当然用手算很费事,我们使用 "M2M 1.0 加密封包分析工具"来计算就方便多了。得到下面的结果:   第一个文件: SEND-> 0000 F4 44 1F 30 6C 79 F6 05 01 01 00 01 00 01 75 09 SEND-> 0010 05 00 CF 26 00 00 00 00 05 00 1C 00 00 00 892 SEND-> 0000 F4 44 0C E3 3B 13 05 00 29 1C 05 083 SEND-> 0000 F4 44 09 D2 7A 00 00 00 484 SEND-> 0000 F4 44 10 DA 01 DB 6C 79 F6 05 02 27 35 01 00 005 SEND-> 0000 F4 44 05 DB 00   第二个档: SEND-> 0000 F4 44 1F 30 6C 79 F6 05 01 01 00 01 00 01 75 09 SEND-> 0010 05 00 70 6B 00 00 00 00 05 00 05 00 00 00 1A2 SEND-> 0000 F4 44 0C E3 3B 13 05 00 29 1C 05 843 SEND-> 0000 F4 44 09 D2 56 00 00 00 484 SEND-> 0000 F4 44 10 DA 01 B8 6C 79 F6 05 02 27 35 01 00 005 SEND-> 0000 F4 44 05 DB 00   哈,这一下两个档大部分都一样啦,说明我们的推理是正确的, 上面就是我们需要的明文!   接下来就是搞清楚一些关键的位元组所代表的含义,这就需要截获大量的资料来分析。   首先我们会发现每个资料包都是"F4 44"开头,第3个位元组是变化的, 但是变化很有规律。 我们来看看各个包的长度,发现什麽没有?对了,第3个位元组就是包的长度!   通过截获大量的资料包,我们判断第4个位元组代表指令, 也就是说用户端告诉伺服器进行的是什麽操作。例如向伺服器请求战斗指令为 "30",战斗中移动指令为"D4"等。 接下来,我们就需要分析一下上面第一个包 "F4 44 1F 30 6C 79 F6 05 01 01 00 01 00 01 75 09 05 00 CF 26 00 00 00 00 05 00 1C 00 00 00 89", 在这个包里包含什麽资讯呢?应该有通知伺服器你PK的哪个NPC吧, 我们就先来找找这个店小二的代码在什麽地方。 我们再PK一个小喽罗(就是大理客栈外的那个咯) :SEND-> 0000 F4 44 1F 30 D4 75 F6 05 01 01 00 01 00 01 75 09  SEND-> 0010 05 00 8A 19 00 00 00 00 11 00 02 00 00 00 C0 我们根据常理分析,游戏里的NPC种类虽然不会超过65535(FFFF) ,但开发时不会把自己限制在字的范围,那样不利於游戏的扩充, 所以我们在双字里看看。通过"店小二"和"小喽罗"两个包的对比,我们把目标放 在"6C 79 F6 05"和"CF 26 00 00"上。 (对比一下很容易的,但你不能太迟钝咯,呵呵) 我们再看看後面的包,在後面的包里应该还会出现NPC的代码, 比如移动的包,游戏允许观战,伺服器必然需要知道NPC的移动座标, 再广播给观战的其他玩家。在後面第4个包 "SEND-> 0000 F4 44 10 DA 01 DB 6C 79 F6 05 02 27 35 01 00 00" 里我们又看到了"6C 79 F6 05",初步断定店小二的代码就是它了! (这分析里边包含了很多工作的,大家可以用WPE截下资料来自己分析分析)     第一个包的分析暂时就到这里(里面还有的资讯我们暂时不需要完全清楚了)   我们看看第4个包 "SEND-> 0000 F4 44 10 DA 01 DB 6C 79 F6 05 02 27 35 01 00 00", 再截获PK黄狗的包,(狗会出来2只哦)看看包的格式: SEND-> 0000 F4 44 1A DA 02 0B 4B 7D F6 05 02 27 35 01 00 00SEND-> 0010 EB 03 F8 05 02 27 36 01 00 00   根据上面的分析,黄狗的代码为 "4B 7D F6 05"(100040011),不过两只黄狗伺服器怎样分辨呢? 看看"EB 03 F8 05"(100140011), 是上一个代码加上100000,呵呵,这样伺服器就可以认出两只黄狗了。 我们再通过野外遇敌截获的资料包来证实,果然如此。   那麽,这个包的格式应该比较清楚了: 第3个位元组为包的长度,"DA"为指令,第5个位元组为NPC个数, 从第7个位元组开始的10个位元组代表一个NPC的资讯, 多一个NPC就多10个位元组来表示。   大家如果玩过网金,必然知道随机遇敌有时会出现增援, 我们就利用游戏这个增援来让每次战斗都会出现增援的NPC吧。   通过在战斗中出现增援截获的资料包, 我们会发现伺服器端发送了这样一个包 :F4 44 12 E9 EB 03 F8 05 02 00 00 03 00 00 00 00 00 00 第5-第8个位元组为增援NPC的代码(这里我们就简单的以黄狗的代码来举例)。 那麽,我们就利用单机代理技术来同时欺骗用户端和伺服器吧!   好了,呼叫NPC的工作到这里算是完成了一小半,接下来的事情, 怎样修改封包和发送封包,我们下节继续讲解吧。   四:怎麽冒充"用户端"向"伺服器"发我们需要的封包?   这里我们需要使用一个工具,它位於用户端和伺服器端之间, 它的工作就是进行资料包的接收和转发,这个工具我们称为代理。 如果代理的工作单纯就是接收和转发的话,这就毫无意义了,但是请注意: 所有的资料包都要通过它来传输,这里的意义就重大了。 我们可以分析接收到的资料包,或者直接转发,或者修改後转发, 或者压住不转发,甚至伪造我们需要的封包来发送。   下面我们继续讲怎样来同时欺骗伺服器和用户端, 也就是修改封包和伪造封包。 通过我们上节的分析,我们已经知道了打多个NPC的封包格式, 那麽我们就动手吧!   首先我们要查找用户端发送的包,找到战斗的特徵, 就是请求战斗的第1个包,我们找"F4 44 1F 30"这个特徵, 这是不会改变的,当然是要解密後来查找哦。 找到後, 表示用户端在向伺服器请求战斗,我们不动这个包,转发。 继续向下查找,这时需要查找的特徵码不太好办,我们先查找"DA", 这是用户端发送NPC资讯的资料包的指令,那麽可能其他包也有"DA" ,没关系,我们看前3个位元组有没有"F4 44"就行了。找到後,我们的工作就开始了!   我们确定要打的NPC数量。这个数量不能很大,原因在於网金的封包长度 用一个位元组表示,那麽一个包可以有255个位元组,我们上面分析过,增加一 个NPC要增加10个位元组,所以大家算算就知道,打20个NPC比较合适。   然後我们要把用户端原来的NPC代码分析计算出来,因为增加的NPC代码 要加上100000哦。再把我们增加的NPC代码计算出来,并且组合成新的封包,注意代表包长度的位元组要修改啊,然後转发到伺服器,这一步在编写程式的时 候要注意演算法,不要造成较大延迟。   上面我们欺骗伺服器端完成了,欺骗用户端就简单了。   发送了上面的封包後,我们根据新增NPC代码构造封包马上发给用户端, 格式就是"F4 44 12 E9 NPC代码 02 00 00 03 00 00 00 00 00 00",把每个新增的 NPC都构造这样一个包,按顺序连在一起发送给用户端,用户端也就被我们骗 过了,很简单吧。   以後战斗中其他的事我们就不管了,尽情地开打吧。 游戏外挂基本原理及实现   游戏外挂已经深深地影响着众多网路游戏玩家,今天在网上看到了一些关於 游戏外挂编写的技术,於是转载上供大家参考   1、游戏外挂的原理   外挂现在分为好多种,比如类比键盘的,滑鼠的,修改资料包的, 还有修改本地记忆体的,但好像没有修改伺服器记忆体的哦,呵呵。 其实修改伺服器也是有办法的,只是技术太高一般人没有办法入手而已。 (比如请GM去夜总会、送礼、收黑钱等等办法都可以修改伺服器资料,哈哈)   修改游戏无非是修改一下本地记忆体的资料,或者截获API函数等等。 这里我把所能想到的方法都作一个介绍,希望大家能做出很好的外挂来使游戏厂 商更好的完善自己的技术。我见到一篇文章是讲魔力宝贝的理论分析, 写得不错,大概是那个样子。下来我就讲解一下技术方面的东西,以作引玉之用。   2 技术分析部分   2.1 类比键盘或滑鼠的回应   我们一般使用:   UINT SendInput(     UINT nInputs,   // count of input events     LPINPUT pInputs, // array of input events     int cbSize    // size of structure   );   API函数。第一个参数是说明第二个参数的矩阵的维数的, 第二个参数包含了回应事件,这个自己填充就可以,最後是这个结构的大小, 非常简单,这是最简单的方法类比键盘滑鼠了,呵呵。 注意,这个函数还有个替代函数:   VOID keybd_event(     BYTE bVk,       // 虚拟键码     BYTE bScan,      // 扫描码     DWORD dwFlags,     ULONG_PTR dwExtraInfo // 附加键状态   );   与   VOID mouse_event(     DWORD dwFlags,      // motion and click options     DWORD dx,         // horizontal position or change     DWORD dy,        // vertical position or change     DWORD dwData,      // wheel movement     ULONG_PTR dwExtraInfo  // application-defined information   );   这两个函数非常简单了,我想那些按键精灵就是用的这个吧。 上面的是类比键盘,下面的是类比滑鼠的。这个仅仅是类比部分, 要和游戏联系起来我们还需要找到游戏的视窗才行,或者包含快捷键, 就象按键精灵的那个启动键一样,我们可以用GetWindow函数来枚举视窗, 也可以用Findwindow函数来查找制定的视窗(注意,还有一个FindWindowEx),FindwindowEx可以找到视窗的子视窗,比如按钮,等什麽东西。 当游戏切换场景的时候我们可以用FindWindowEx来确定一些当前视窗的特徵, 从而判断是否还在这个场景,方法很多了,比如可以GetWindowInfo来确定一些 东西,比如当查找不到某个按钮的时候就说明游戏场景已经切换了,等等办法。 有的游戏没有控制项在里面,这是对图像做座标变换的话, 这种方法就要受到限制了。这就需要我们用别的办法来辅助分析了。   至於快捷键我们要用动态连接库实现了,里面要用到hook技术了,这个也非常简单。 大家可能都会了,其实就是一个全局的hook物件然後SetWindowHook就可以了, 回调函数都是现成的,而且现在网上的例子多如牛毛。 这个实现在外挂中已经很普遍了。如果还有谁不明白,那就去看看MSDN查找SetWindowHook就可以了。   不要低估了这个动态连接库的作用,它可以切入所有的进程空间, 也就是可以载入到所有的游戏里面哦,只要用对,你会发现很有用途的。 这个需要你复习一下Win32编程的基础知识了。呵呵,赶快去看书吧。   2.2 截获消息   有些游戏的回应机制比较简单,是基於消息的,或者用什麽计时器的东西。 这个时候你就可以用拦截消息来实现一些有趣的功能了。   我们拦截消息使用的也是hook技术,里面包括了键盘消息,滑鼠消息, 系统消息,日志等,别的对我们没有什麽大的用处, 我们只用拦截消息的回调函数就可以了,这个不会让我写例子吧。 其实这个和上面的一样,都是用SetWindowHook来写的,看看就明白了很简单的。   至於拦截了以後做什麽就是你的事情了,比如在每个计时器消息里面处理一 些我们的资料判断,或者在计时器里面在模拟一次计时器,那麽有些资料就会处 理两次,呵呵。後果嘛,不一定是好事情哦,呵呵,不过如果资料计算放在用户 端的游戏就可以真的改变资料了,呵呵,试试看吧。 用途还有很多,自己想也可以想出来的,呵呵。   2.3 拦截Socket包   这个技术难度要比原来的高很多。   首先我们要替换WinSock.DLL或者WinSock32.DLL, 我们写的替换函数要和原来的函数一致才行,就是说它的函数输出什麽样的, 我们也要输出什麽样子的函数,而且参数,参数顺序都要一样才行, 然後在我们的函数里面调用真正的WinSock32.DLL里面的函数就可以了。   首先:我们可以替换动态库到系统路径。   其次:我们应用程式启动的时候可以载入原有的动态库, 用这个函数LoadLibary然後定位函数入口用GetProcAddress函数获得每个真正Socket函数的入口位址。   当游戏进行的时候它会调用我们的动态库,然後从我们的动态库中处理完毕 後才跳转到真正动态库的函数位址,这样我们就可以在里面处理自己的资料了, 应该是一切资料。呵呵,兴奋吧,拦截了资料包我们还要分析之後才能进行正确 的应答,不要以为这样工作就完成了,还早呢。等分析完毕以後我们还要仿真应 答机制来和伺服器通信,一个不小心就会被封号。   分析资料才是工作量的来源呢,游戏每次升级有可能加密方式会有所改变, 因此我们写外挂的人都是亡命之徒啊,被人愚弄了还不知道。   2.4 截获API   上面的技术如果可以灵活运用的话我们就不用截获API函数了, 其实这种技术是一种补充技术。比如我们需要截获Socket以外的函数作为我们 的用途,我们就要用这个技术了,其实我们也可以用它直接拦截在Socket中的 函数,这样更直接。   现在拦截API的教程到处都是,我就不列举了,我用的比较习惯的方法是 根据输入节进行拦截的,这个方法可以用到任何一种作业系统上,比如Windows 98/2000等,有些方法不是跨平台的,我不建议使用。这个技术大家可以参考 《Windows核心编程》里面的545页开始的内容来学习,如果是Win98系统可 以用“Windows系统奥秘”那个最後一章来学习。 网路游戏外挂核心封包揭密   网路游戏的封包技术是大多数编程爱好者都比较关注的关注的问题之一, 在这里就让我们一起研究一下这一个问题吧。   别看这是封包这一问题,但是涉及的技术范围很广范,实现的方式也很多 (比如说APIHOOK,VXD,Winsock2都可以实现),在这里我们不可能每种技术 和方法都涉及,所以我在这里以Winsock2技术作详细讲解,就算作?砖引玉。   由於大多数读者对封包类编程不是很了解,我在这里就简单介绍一下相关知识:   APIHooK:   由於Windows的把内核提供的功能都封装到API里面,所以大家要实现功 能就必须通过API,换句话说就是我们要想捕获资料封包,就必须先要得知道并 且捕获这个API,从API里面得到封包资讯。   VXD:   直接通过控制VXD驱动程式来实现封包资讯的捕获, 不过VXD只能用於win9X。   winsock2:   winsock是Windows网路编程介面,winsock工作在应用层, 它提供与底层传输协定无关的高层资料传输编程介面,winsock2是winsock2.0 提供的服务提供者介面,但只能在win2000下用。   好了,我们开始进入winsock2封包式编程吧。   在封包编程里面我准备分两个步骤对大家进行讲解:1、封包的捕获,2、封包的发送。   首先我们要实现的是封包的捕获:   Delphi的封装的winsock是1.0版的,很自然winsock2就用不成。 如果要使用winsock2我们要对winsock2在Delphi里面做一个介面, 才可以使用winsock2。   1、如何做winsock2的介面? 1) 我们要先定义winsock2.0所用得到的类型, 2) 在这里我们以WSA_DATA类型做示范,大家可以举一仿三的来实现 winsock2其他类型的封装。   我们要知道WSA_DATA类型会被用於 WSAStartup(wVersionRequired: word; var WSData: TWSAData): Integer;,大家会发现WSData是引用参数,在传入参数时传的是变 数的位址,所以我们对WSA_DATA做以下封装: const WSADEforbiddenION_LEN = 256; WSASYS_STATUS_LEN = 128; type PWSA_DATA = ^TWSA_DATA; WSA_DATA = record wVersion: Word; wHighVersion: Word; szDeforbiddenion: array[0..WSADEforbiddenION_LEN] of Char; szSystemStatus: array[0..WSASYS_STATUS_LEN] of Char; iMaxSockets: Word; iMaxUdpDg: Word; lpVendorInfo: PChar; end; TWSA_DATA = WSA_DATA;   2)我们要从WS2_32.DLL引入winsock2的函数,在此我们也是以WSAStartup为例做函数引入: function WSAStartup(wVersionRequired: word; var WSData: TWSAData): Integer; stdcall; implementation const WinSocket2 = 'WS2_32.DLL'; function WSAStartup; external winsocket name 'WSAStartup';   通过以上方法,我们便可以对winsock2做介面,下面我们就可以用winsock2做封包捕获了,不过首先要有一块网卡。 因为涉及到正在运作的网路游戏安全问题, 所以我们在这里以IP资料包为例做封包捕获, 如果下面的某些资料类型您不是很清楚,请您查阅MSDN:   1)我们要起动WSA,这时个要用到的WSAStartup函数,用法如下: INTEGER WSAStartup(  wVersionRequired: word,  WSData: TWSA_DATA );    2)使用socket函数得到socket控制码,m_hSocket:=Socket(AF_INET, SOCK_RAW, IPPROTO_IP); 用法如下: INTEGER socket(af: Integer, Struct: Integer, protocol: Integer ); m_hSocket:=Socket(AF_INET, SOCK_RAW, IPPROTO_IP);   在程式里m_hSocket为socket控制码,AF_INET,SOCK_RAW,IPPROTO_IP均为常量。   3)定义SOCK_ADDR类型,跟据我们的网卡IP给Sock_ADDR类型附值,然後我们使用bind函数来绑定我们的网卡,Bind函数用法如下: Type IN_ADDR = record S_addr : PChar; End; Type TSOCK_ADDR = record sin_family: Word; sin_port: Word; sin_addr : IN_ADDR sin_zero: array[0..7] of Char; End; var LocalAddr:TSOCK_ADDR; LocalAddr.sin_family: = AF_INET; LocalAddr.sin_port: = 0; LocalAddr.sin_addr.S_addr: = inet_addr('192.168.1.1'); //这里你自己的网卡的IP位址,而inet_addr这个函数是winsock2的函数。 bind(m_hSocket, LocalAddr, sizeof(LocalAddr));   4)用WSAIoctl来注册WSA的输入输出元件,其用法如下: INTEGER WSAIoctl(s:INTEGER, dwIoControlCode : INTEGER, lpvInBuffer :INTEGER, cbInBuffer : INTEGER, lpvOutBuffer : INTEGER, cbOutBuffer: INTEGER, lpcbBytesReturned : INTEGER, lpOverlapped : INTEGER, lpCompletionRoutine : INTEGER );   5)下面做闭环,在闭环块里,来实现资料的接收。但是徇环中间要用Sleep()做延时,不然程式会出错。   6)在回圈块里,用recv函数来接收资料,recv函数用法如下: INTEGER recv (s : INTEGER, buffer:Array[0..4095] of byte, length : INTEGER, flags : INTEGER, );   7)在buffer里就是我们接收回来的资料了,如果我们想要知道资料是什麽地方发来的,那麽, 我们要定义一定IP包结构,用CopyMemory()把IP资讯从buffer里面读出来就可以了, 不过读出来的是十六进位的资料需要转换一下。   看了封包捕获的全过程式,对你是不是有点起发,然而在这里要告诉大家的 是封包的获得是很容易的,但是许多游戏的封包都是加密的,如果你想搞清楚所 得到的是什麽内容还需要自己进行封包解密。 四种网路游戏外挂的设计方法   在几年前我看到别人玩网路游戏用上了外挂,做为程式师的我心里实在是不 爽,想搞清楚这到底是怎麽回事。就拿了一些来研究,小有心得,拿出来与大家 共用,外挂无非就是分几种罢了(依制作难度):   1、动作式,所谓动作式,就是指用API发命令给视窗或API控制滑鼠、 键盘等,使游戏里的人物进行流动或者攻击,最早以前的“石器”外挂就是这种方式。 (这种外挂完全是垃圾,TMD,只要会一点点API的人都知道该怎麽做,不过 这种外挂也是入门级的好东东,虽然不能提高你的战斗力,但是可以提高你的士 气)   2、本地修改式,这种外挂跟传统上的一些游戏修改器没有两样, 做这种外挂在编程只需要对记忆体位址有一点认识并且掌握API就可以实现, “精灵”的外挂这是这种方式写成的,它的难点在於找到那些位址码, 找位址一般地要借助於别人的工具,有的游戏还有双码校验,正正找起来会比较 困难。(这种外挂,比上一种有一点点难度,但是这种外挂做起来能够用, 也是有一定难度的啦~~,这种外挂可以很快提升你对记忆体位址的理解及应用, 是你编程技术提高的好东东)   3、木马式,这种外挂的目的是帮外挂制作者偷到用户的密码 (TMD,“烂”就一个字,不过要知已知彼所以还是要谈一下啦~~), 做这种外挂有一定的难度,需要HOOK或键盘监视技术做底子,才可以完成, 它的原理是先首截了用户的帐号或密码,然後发到指定邮箱。 (我以前写过这样的东东,但是从来没有用过,我知道这种东东很不道德, 所以以後千万别用呀!)   4、加速式,这种外挂可以加快游戏的速度…… (对不起大家,这种东东我没有实际做过,所以不能妄自评,惭愧)   这几种外挂之中,前三种可以用VB,Delphi等语言比较好实现, 後两种则要用VC等底层支援比较好的编程工具才好实现。   动作式外挂   首先,先来谈一下动作式的外挂,这也是我第一次写外挂时做的最简单的一种。   记得还在“石器”时代的时候,我看到别人挂着一种软体(外挂) 人物就可以四外游走(当时我还不知道外挂怎麽回事), 於是找了这种软体过来研究(拿来後才听别人说这叫外挂), 发现这种东东其实实现起来并不难,仔佃看其实人物的行走无非就是滑鼠在不同的地方点来点去而已, 看後就有实现这功能的冲动,随後跑到MSDN上看了一些资料,发现这种实现 这几个功能,只需要几个简单的API函数就可以搞定: 1、 首先我们要知道现在滑鼠的位置(为了好还原现在滑鼠的位置) 所以我们就要用到API函数GetCursorPos,它的使用方法如下: BOOL GetCursorPos( LPPOINT lpPoint // address of structure for cursor position ); 2、 我们把滑鼠的位置移到要到人物走到的地方, 我们就要用到SetCursorPos函数来移动滑鼠位置,它的使用方法如下: BOOL SetCursorPos( int X, // horizontal position int Y // vertical position );   3、类比滑鼠发出按下和放开的动作,我们要用到mouse_event函数来实现,具休使用方法用下: VOID mouse_event( DWORD dwFlags, // flags specifying various motion/click variants DWORD dx, // horizontal mouse position or position change DWORD dy, // vertical mouse position or position change DWORD dwData, // amount of wheel movement DWORD dwExtraInfo // 32 bits of application-defined information );   在它的dwFlags处,可用的事件很多如移动MOUSEEVENTF_MOVE, 左键按下MOUSEEVENTF_LEFTDOWN,左键放开MOUSEEVENTF_LEFTUP, 具体的东东还是查一下MSDN吧~~~~~    好了,有了前面的知识,我们就可以来看看人物移走是怎麽实现的了: getcursorpos(point); setcursorpos(ranpoint(80,windowX),ranpoint(80,windowY)); //ranpoint是个自制的随机座标函数 mouse_event(MOUSEEVENTF_LEFTDOWN,0,0,0,0); mouse_event(MOUSEEVENTF_LEFTUP,0,0,0,0); setcursorpos(point.x,point.y);   看了以上的代码,是不是觉得人物的游走很简单啦~~,举一仿三, 还有好多好东东可以用这个技巧实现 (我早就说过,TMD,这是垃圾外挂的做法,相信了吧~~~), 接下来,再看看游戏里面自动攻击的做法吧(必需游戏中攻击支持快捷键的), 道理还是一样的,只是用的API不同罢了~~~, 这回我们要用到的是keybd_event函数,其用法如下: VOID keybd_event( BYTE bVk, // virtual-key code BYTE bScan, // hardware scan code DWORD dwFlags, // flags specifying various function options DWORD dwExtraInfo // additional data associated with keystroke ); 我们还要知道扫描码不可以直接使用,要用函数MapVirtualKey把键值转成扫描码, MapVirtualKey的具体使用方法如下: UINT MapVirtualKey( UINT uCode, // virtual-key code or scan code UINT uMapType // translation to perform );   好了,比说此快接键是CTRL+A,接下来让我们看看实际代码是怎麽写的: keybd_event(VK_CONTROL,mapvirtualkey(VK_CONTROL,0),0,0); keybd_event(65,mapvirtualkey(65,0),0,0); keybd_event(65,mapvirtualkey(65,0),keyeventf_keyup,0); keybd_event(VK_CONTROL,mapvirtualkey(VK_CONTROL,0),keyeventf_keyup,0);   首先模拟按下了CTRL键,再模拟按下A键,再模拟放开A键, 最後放开CTRL键,这就是一个模拟按快捷键的周期。   (看到这里,差不多对简易外挂有了一定的了解了吧~~~~做一个试试? 如果你举一仿三还能有更好的东东出来,这就要看你的领悟能力了~~, 不过不要高兴太早这只是才开始,以後还有更复杂的东东等着你呢~~)   本地修改式外挂   现在我们来看看,比动作式外挂更进一步的外挂——本地修改式外挂的整个 制作过程进行一个详细的分解。   具我所知,本地修改式外挂最典型的应用就是在“精灵”游戏上面, 因为我在近一年前(“精灵”还在测试阶段),我所在的公司里有很多同事玩 “精灵”,於是我看了一下游戏的资料处理方式, 发现它所发送到伺服器上的资讯是存在於记忆体当中 (我看後第一个感受是:修改这种游戏和修改单机版的游戏没有多大分别, 换句话说就是在他向伺服器提交资讯之前修改了记忆体位址就可以了), 当时我找到了位址於是修改了记忆体位址,果然,按我的想法修改了位址, 让系统自动提交後,果然成功了~~~~~,後来“精灵”又改成了双位址校检, 记忆体校检等等,在这里我就不废话了~~~~,OK, 我们就来看看这类外挂是如何制作的:   在做外挂之前我们要对Windows的记忆体有个具体的认识, 而在这里我们所指的记忆体是指系统的记忆体偏移量,也就是相对记忆体, 而我们所要对其进行修改,那麽我们要对几个Windows API进行了解,OK,跟着例子让我们看清楚这种外挂的制作和API的应用 (为了保证网路游戏的正常运行,我就不把找记忆体位址的方法详细解说了): 1、 首先我们要用FindWindow,知道游戏视窗的控制码, 因为我们要通过它来得知游戏的运行後所在进程的ID, 下面就是FindWindow的用法: HWND FindWindow( LPCTSTR lpClassName, // pointer to class name LPCTSTR lpWindowName // pointer to win -- ◎(bbs.mgt.ncu.edu.tw) ◎[brucetsao]From: 59-115-92-61.dynamic.hinet.net







like.gif 您可能会有兴趣的文章
icon.png[问题/行为] 猫晚上进房间会不会有憋尿问题
icon.pngRe: [闲聊] 选了错误的女孩成为魔法少女 XDDDDDDDDDD
icon.png[正妹] 瑞典 一张
icon.png[心得] EMS高领长版毛衣.墨小楼MC1002
icon.png[分享] 丹龙隔热纸GE55+33+22
icon.png[问题] 清洗洗衣机
icon.png[寻物] 窗台下的空间
icon.png[闲聊] 双极の女神1 木魔爵
icon.png[售车] 新竹 1997 march 1297cc 白色 四门
icon.png[讨论] 能从照片感受到摄影者心情吗
icon.png[狂贺] 贺贺贺贺 贺!岛村卯月!总选举NO.1
icon.png[难过] 羡慕白皮肤的女生
icon.png阅读文章
icon.png[黑特]
icon.png[问题] SBK S1安装於安全帽位置
icon.png[分享] 旧woo100绝版开箱!!
icon.pngRe: [无言] 关於小包卫生纸
icon.png[开箱] E5-2683V3 RX480Strix 快睿C1 简单测试
icon.png[心得] 苍の海贼龙 地狱 执行者16PT
icon.png[售车] 1999年Virage iO 1.8EXi
icon.png[心得] 挑战33 LV10 狮子座pt solo
icon.png[闲聊] 手把手教你不被桶之新手主购教学
icon.png[分享] Civic Type R 量产版官方照无预警流出
icon.png[售车] Golf 4 2.0 银色 自排
icon.png[出售] Graco提篮汽座(有底座)2000元诚可议
icon.png[问题] 请问补牙材质掉了还能再补吗?(台中半年内
icon.png[问题] 44th 单曲 生写竟然都给重复的啊啊!
icon.png[心得] 华南红卡/icash 核卡
icon.png[问题] 拔牙矫正这样正常吗
icon.png[赠送] 老莫高业 初业 102年版
icon.png[情报] 三大行动支付 本季掀战火
icon.png[宝宝] 博客来Amos水蜡笔5/1特价五折
icon.pngRe: [心得] 新鲜人一些面试分享
icon.png[心得] 苍の海贼龙 地狱 麒麟25PT
icon.pngRe: [闲聊] (君の名は。雷慎入) 君名二创漫画翻译
icon.pngRe: [闲聊] OGN中场影片:失踪人口局 (英文字幕)
icon.png[问题] 台湾大哥大4G讯号差
icon.png[出售] [全国]全新千寻侘草LED灯, 水草
伺服器连线错误,造成您的不便还请多多包涵!
「赞助商连结」






like.gif 您可能会有兴趣的文章
icon.png[问题/行为] 猫晚上进房间会不会有憋尿问题
icon.pngRe: [闲聊] 选了错误的女孩成为魔法少女 XDDDDDDDDDD
icon.png[正妹] 瑞典 一张
icon.png[心得] EMS高领长版毛衣.墨小楼MC1002
icon.png[分享] 丹龙隔热纸GE55+33+22
icon.png[问题] 清洗洗衣机
icon.png[寻物] 窗台下的空间
icon.png[闲聊] 双极の女神1 木魔爵
icon.png[售车] 新竹 1997 march 1297cc 白色 四门
icon.png[讨论] 能从照片感受到摄影者心情吗
icon.png[狂贺] 贺贺贺贺 贺!岛村卯月!总选举NO.1
icon.png[难过] 羡慕白皮肤的女生
icon.png阅读文章
icon.png[黑特]
icon.png[问题] SBK S1安装於安全帽位置
icon.png[分享] 旧woo100绝版开箱!!
icon.pngRe: [无言] 关於小包卫生纸
icon.png[开箱] E5-2683V3 RX480Strix 快睿C1 简单测试
icon.png[心得] 苍の海贼龙 地狱 执行者16PT
icon.png[售车] 1999年Virage iO 1.8EXi
icon.png[心得] 挑战33 LV10 狮子座pt solo
icon.png[闲聊] 手把手教你不被桶之新手主购教学
icon.png[分享] Civic Type R 量产版官方照无预警流出
icon.png[售车] Golf 4 2.0 银色 自排
icon.png[出售] Graco提篮汽座(有底座)2000元诚可议
icon.png[问题] 请问补牙材质掉了还能再补吗?(台中半年内
icon.png[问题] 44th 单曲 生写竟然都给重复的啊啊!
icon.png[心得] 华南红卡/icash 核卡
icon.png[问题] 拔牙矫正这样正常吗
icon.png[赠送] 老莫高业 初业 102年版
icon.png[情报] 三大行动支付 本季掀战火
icon.png[宝宝] 博客来Amos水蜡笔5/1特价五折
icon.pngRe: [心得] 新鲜人一些面试分享
icon.png[心得] 苍の海贼龙 地狱 麒麟25PT
icon.pngRe: [闲聊] (君の名は。雷慎入) 君名二创漫画翻译
icon.pngRe: [闲聊] OGN中场影片:失踪人口局 (英文字幕)
icon.png[问题] 台湾大哥大4G讯号差
icon.png[出售] [全国]全新千寻侘草LED灯, 水草

请输入看板名称,例如:Soft_Job站内搜寻

TOP