俗话说隔行如隔山,感觉上是一回事,自己动手又是另一回事.这两天回家就帮亲戚家孩子做外挂,本以为很简单,结果泡广海逛看雪的,研究了三个半晚上才在今天接近凌晨时大体弄好.万幸自己一直在混软件这碗饭,并没真正的隔行,最多是"一座山上两座峰,搭个吊桥就能通"罢了.
前两天博文中提过一次,这次帮亲戚做外挂为了省事没做封包的(事实上没写过外挂,也不敢写封包的),只是利用程序自身CALL指令在模拟事件, 写的"内挂"罢了.个人以为,写这类东西主要难在脱壳和过防护,过去便一马平川,真正开发时的问题反而很少.
大前天写过一个Java的汇编混合类库,刚才写外挂时顺便给它添了点东西,又根据广海的找CALL入门示例延伸出一个Java版的实现,现发布于此博客,欢迎有兴趣者帮忙继续完善类库.
——————————————————————————————————————————————————————
愚以为,Java做外挂开发有优点如下:
1、隐蔽性高:由于标准Java程序在运行时仅会显示主线程,也就是Java或者Javaw,开发商将很难据此判断外挂进程的使用状态(想查标题和窗体类名识别?1秒能随机换N个);而对于特征码识别,Java的解释型特点令class完全能够做到动态随机构建,完全可以自动变更特征码,让屏蔽软件防不胜防。也就是说,大多数针对exe文件的监测方法,并不能很好的对Java通用,Java外挂将有较高的隐蔽性。当然,也许你会说厂商可以干脆停止所有Java进程。是的,可与此同时,这也意味着厂商的开发人员承认了自己的无能——由于识别不出犯人,只好见人就杀。如果偏巧赶上个用永中office之类Java软件工作的主,结果没保存就被游戏强断了(或者开着Java进不去游戏,一样会有人抗议),便有热闹可看^^另外相关人等大可以在背后写信鼓动Sun或者IBM对厂商提出交涉(有炒作的价值,他们不一定不管哦~),再不然借机把相关资料和截图发往各大Java社区,不用咱们动手,他们的游戏就会被疯狂修改,甚至连源码都被发上网来……
2、先天适合注入操作:我们都知道JNI不光能调用本地接口,也能让本地程序动态调用指定Java类及相关函数,而对于其他语言来说,这是较难实现的;只要善于利用这点,我们便可以令实现了JNI接口的DLL文件充当发报器,而让Java平台充当中间件,最大限度的扩展功能,并以此为基础提供便利的进程间通信。
3、跨平台:我们心理都很清楚,Java并没有真正意义上的跨平台,Java本身即是一个平台,只不过针对不同的操作系统有不同的版本罢了。但是,只要对于用户体验而言,Java是在跨平台,便已经足够了。如果那天你开发的网游在其他系统出了新版,你同样可以在不改变原有外挂UI及外部接口的情况下追过去,而且是游戏敢做到什么系统,你就敢追到什么系统。还有一点,对于完全脱机版的封包外挂而言,Java能让你的用户在绝大多数时候,绝大多数系统中,坚持挂机不动摇……
4、开发封包类外挂便利:Java提供的网络通讯功能是非常强大的,并且有大量第三方组件支持,对于脱机的封包外挂而言,Java实现远比C/C++实现简单,另外跨平台在第三点已经强调了。
5、开发周期短,适合团队协作:Java先天具有适合商业开发的基因,团队协作开发对于熟悉Java者也只是小菜一碟罢了。Java代码的可读性相较C/C++或者Delphi而言要更好些,调试也更简单,有助于你的外挂早日上市。
缺憾:
不知道。(对于Java所有缺点,鄙人认为都有方案解决,所以暂时没想到缺点:))
关于找Call部分,直接转载自广海社区,发帖人为[gao6621],原文地址:
说实话,上面这个例子也算直观到了极限,乃至于不开OD也能直接通过反汇编猜出触发点......
反汇编截图如下:
注意看,所有call附近都能找到技能名的中文字符串|||,要是网游也都写成这样就好了~~~
当然这无关紧要,最主要的讲解目的上述文章已经足够实现了.但是,文章中却有些地方没有点到,我在此略微做下补充.
客观上讲,这篇找CALL入门的作者似乎是有意没有说全,尤其是关于寄存器中的数值部分.我们都知道,内存中的数据并不是绝对恒定的,大多数时候寄存器显示的实际上是可变值,只是某些情况下某些数值相对固定于本机而已.比如转载的例子中,作者获得的数值为005D1FE4,而在我自家机器上却是00D52070,如果强行在我机器上注入该示例作者的数值,则会引发如下图事件.
点了一次回城,没想到却让测试程序崩溃回老家结婚去了|||
为什么呢?原因很简单,在不同机器上,寄存器中EAX这个值是不同的,数据错误当然会造成程序异常.
但是,我们总不可能分别为每一个用户都订制程序吧?即便我们把源码给出去让用户自行修改后编译,估计一般用户也不会(^^).所以这时,就需要用其它手段来获得这个变化的EAX数值.
要找出测试程序在不同机器上的EAX值并不难.对于我们这代人而言,以前大多曾干过类似的事情.而说到我第一次干这种事,还是在智冠刚出单机版金庸群侠转时.当时我用DOS下某游戏修改器调十级野球拳,却几乎不会用,仅仅是看书改的......到了现今,修改单机游戏各项参数对我们来讲已经是再简单不过的一件事情,用游戏修改工具我们可以轻松检索出游戏中的各种数据并使之变化为我们的满意结果.(据说有部分神仙级网游,也可以直接用修改器修改,服务器照认不误.另外我承认N年前玩网金建号时偶用修改大师改初始根骨了- -)
好了,说到这里大家应该都知道我想说什么了,我们很清楚游戏中的数值并非必须依照编码变化,人为也可以加以修改的.但是,我们的修改的数据,都改到什么地方去了呢?实际上,在修改游戏时,和数据项始终对应的,就是地址项.数值可以变,但是保存数值的地址却绝对没法变.无论我们将单机金庸中的生命金钱武功悟性等数字项改成多高或多低,也始终不能令游戏主角的攻击力变成[葵花宝典]这组字符串后,还令游戏正常运行(实际上可以做到的,但就不是单纯的修改数值了).那么,对于我们已经能得到的本机EAX数值,能不能找到存放这个数值的地址呢?---答案是肯定的.
这里我们使用Cheat Engine来附加[游戏找CALL练习实例one]进程进行(用游戏修改大师,金山游侠等同样能找到,CE功能更多而已),而后以16进搜索我机器上的EAX数值[00D52070](不固定,都去找自己机器上的去~),以精确方式进行查找.
这时,CE截取到数值如下图:
我们可以清楚地看到地址与数值的对应关系,在本次操作中包含有[00D52070]的地址有40个,但究竟那个是我们需要的呢?
修改过游戏的都知道,此刻只需耐心多操作几次,观察地址中数值的变化,总会有一部分数据被剃掉,而另一些却始终存在.最后,我们可以发现,顶头的00456D68这个地址,就是我们所需要的.
这时,我们在Java程序中只要用LocalOS中OSProcess类下的readProcessMemory读取练习程度的进程内存中的00456D68地址。
即使用:
- OSProcess.readProcessMemory(pid, 0x456D68)
这样,就可以取得本机在CALL时需要的EAX数值了,我机器上是[00D52070]。
要在程序找到一个数值的变化规律是不容易的事情,但是找一个地址却是相对容易的,只要游戏不更新,这个地址就是固定的,有了这个通用的地址,我们的程序就可以运行在不同配置的机器之上.
另外还有一点需要说明的是,bp send命令触发的断点仅在OD截获程序发包时启动,这点找CALL这篇文章没有提及,这里补充一下.
现在必要的条件已经都具备了,我来用Java编写一个Java汇编的演示类,以演示代码注入方式触发目标程序CALL.
现在我们执行代码,可以见到结果如下图: 最后,再额外补充两点: 一,示例程序和真正的CALL外挂开发虽然原理上一样,工作量却是天差地别的,时间不充裕者请不要轻易尝试--||| 二,这个示例仅仅演示了localos的一部分功能,比如dll注入的接口在其中也提供了, 有兴趣者可以尝试一下,但要注意权限问题. 程序源码及示例下载地址: (暂时先丢这里,源码在jar内)
阅读(748) | 评论(0) | 转发(0) |