首页
社区
课程
招聘
[原创]对韩国原装X游戏的服务器端及客户端加固
发表于: 2010-2-1 03:26 32540

[原创]对韩国原装X游戏的服务器端及客户端加固

2010-2-1 03:26
32540

近日受一位朋友委托,对他公司运营的游戏服务器端及客户端做加固。该游戏暂称为X

X是个韩国游戏,得过很多奖项,据公开资料,其几年前的代理费为500万美元。韩国开发团队的软件工程效率很高,政 府也出面组织引擎共享,代码复用,所以,如果你逆向了多个韩国游戏,你会发现他们的代码复用率很高,当然,正如我们调侃某人考试作弊一样:“你抄就抄了,怎么把别人名字也写在自己考卷上了?”是的,多数韩国游戏连bug都很相似。

X这个游戏,Server端既有在Linux上的,也有在Windows上的,而且我没有源代码,一切工作只能从逆向入手。Windows上的Crack、Hook、Patch资料都很多,但是Linux上的一切都要靠摸索了(当然,Linux的相关源代码都是开放的,你随时都可以参考)。

用Linux或*BSD做Server的游戏很多,但他的开发门槛高,周期长,而且一旦开发完成,维护成本也高,维护人员的素质也要求高。所以,用Linux做Server的游戏,比例不大,但是数量也不少,国内有很多公司用Linux/*BSD做Server,如ZT,WM,WL

本人与运营商详细沟通及认真逆向分析后,得出这个X游戏致命问题如下:
1.        因对recv缓冲区长度的判断不严谨及具体协议Command有漏洞,存在缓冲区溢出的问题。轻则受到攻击后Server崩溃,重则被精心构造的ShellCode执行了恶意操作,例如添加个超级用户之类的,死都不知道是怎么死的。
2.        该游戏曾经狂受欢迎(代理费竞争到了500万美元就能说明问题了),所以至今仍有外挂小组孜孜不倦地为他开发外挂。到现在,通讯协议的加密,资源的打包及加密,几乎都赤裸裸地呈现在外挂小组面前了,他们几乎可以随心所欲地实现他们的功能(随意踢别人下线),因此,我需要与这种恶意外挂正面作战(本人不鄙视外挂,只是立场不同,需要对抗恶意外挂而已)。
3.        Server端未做穿墙加速判断,导致游戏中外挂可以穿墙加速,甚至改资源文件都可以穿墙。
4.        GameServer与LoginServer上的玩家OnlineTag没有严格同步,当网络异常时(外挂可以有意模拟出异常),装备可以被复制。
5.        对不良网络情况未做容错判断,微小的网络异常,都会导致客户断开。所以,如果服务器架在电信,而跨ISP去联他(例如铁通、网通、XX),断线的概率非常大。知道的人说是Server程序先天不足,不知道的,还以为是运营商没有实力,舍不得花钱买好机器买好带宽。所以,客户流失率很高。
其他非致命问题如下:
6.        原装的Server端中,GameServer需要2台服务器,而现在随着硬件的发展,以前2台Server干的活,现在1台也完全能胜任,所以我的任务是,尽最大可能修改bin文件,使之用1台GameServer就能搞定,这样,即省IP,又省维护资源。

以上问题,韩国官方至今没有解决,其结果,就是造成了X这款挺好玩的游戏,韩国、日本、大陆、台湾、香港、东南亚、美国官服都很难运营,几百万美元打了水漂。到现在,官服几乎像个弃儿,玩家爱来玩就玩,不来玩也不宣传;来玩的人,能忍受就忍受,受不了就走人。

该游戏Server及Client都有NP SDK,客观地说,用了NP SDK,的确强度比没用SDK好,但是强中自有强中手,外挂小组已经fuck 了NP。而我们对Server和Client的加固,不能脱下美丽的NP外衣,否则赤裸裸的游戏,不是更容易被更多的外挂小组蹂躏?所以,我们应在不触动NP的情况下,对NP做改进和补充,假如NP是美丽外衣的话,我们的改动就是加个围巾。

解决步骤:
第一、首先是静态分析,假如有加壳,那么就需要脱壳分析,或直接分析内存。
第二、动态分析,用调试器去运行之,并且设置合适断点,观察其软件的运行方式。
第三、模拟故障的发生,尝试解决之。
第四、有了成熟的解决代码后,将其嵌入到目标bin文件中。

前面的第1,2,3,都是与具体的应用紧密相关的。关于第4点,比较通用,我是采用将目标bin中的汇编代码重新优化整理,删除冗余代码,对相对的jmp/call/内存引用等做重定位处理。
部分冗余代码如下:

当删除冗余代码,其余代码向上做靠拢后,会出现1个问题,相对jmp/call/地址引用等,会错误,所以这里还需要修正,修正时,分2种情况:假如DstAddr在本次优化整理范围内,其地址会变化,则用DstAddr的新地址-当前指令执行完后的EIP做为新的EIP修正量;假如DstAddr在本次优化范围外,其地址不变,则用当前指令的的相对优化移动量去修正。
经过汇编级别的优化整理,基本上空间足够我们添加代码,不需要增加新的Section,实现ZeroAdd.

可能有同学会问,你调整那么多汇编代码,多累啊,还要计算,太容易出错了,为什么不用高级语言写个hooker,hook在合适的点呢?

我对此的回答及做法是:
window上可执行程序是exe/com/dll/sys,PE结构,linux上文件扩展名没有强制要求,文件结构也不是PE,是ELF结构。如果我们对目标bin程序的改进,是用UltraEdit逐个字节加入的话,当修改规模大到一定程度的时候,会出现以下问题:
1:在我们尝试修正的时候,我们很难控制各个测试版本是否会混乱。
2:假设A bug的修正集合是改动了5处,B bug的修正集合是改动了6处,显然,在不断的尝试中,我们会因为这些修正的组合错误或改动点的不小心错误,带来更大的问题。
3:可能因为修正A bug引入A+ bug,

而我换个思维,先去磨了刀,再来砍柴,自己写了个程序,能作到以下要求:
1:对指定bin程序(PE/ELF都可)中某Section一定范围内的汇编程序自动做优化调整。该删的删、该插的插,优化后的汇编指令直接向前靠,同时能修正相对jmp/call/内存引用。
2:自动修改PE/ELF文件,自动嵌入汇编代码(用VC++和GNUC++写,编译后摘出关键汇编代码,修正),这样可以使得我能从高级语言的视角去看整体的改进,所以即使改动很大,从思维上也能控制整个程序的改进,不会版本错乱,而且降低修正某bug带来新bug的可能性
如果能站在高级语言的角度去看整个程序及所有改进,并且有足够空间容纳我们的汇编代码,其实这时候已经不需要用hooker了。
本人修正了以上6个bug,改动近300处

2010-1-31,本人对原装韩国程序和经本人修改后的程序,做了对比测试,列表如下:

以上测试严格按照同等环境测试,每测试大项完毕1次,都会关机,停10秒,再开机,以消除内存残留数据的影响,测试小项完毕不关机。
以上环境为:
E5300 CPU 4G内存机,
------------------------------------------------------------------------
关于优化汇编,调整汇编代码次序省出空间,放我们patch的好处,请见下面例子。
例如附件中的patchme.exe
以下lea esi,[esi]之类的align代码,在实际程序中一般会存在,我为了将函数尽可能在同个屏幕内显示出来,所以构造了个小函数,并人工加了这些align代码进去,以利于理解。

其中
.text:00401071 6A 30                    push 30h
.text:00401073 E8 88 FF FF FF           call Test1
如果我们想push 1个正整数144,给函数Test1,即
push 0x90
call Test1
不能直接改成6A 90,因为6A是push 1个BYTE,如果你6A 90,会符号扩展,变成push 0xFFFFFF90,变成负数了,显然,我们应该用
68 90 00 00 00           push 90h
这才是push 1个DWORD,而这时候,00401071的空间不够我们直接改的,如果我们能将函数中汇编代码优化并整理,调整相对jmp/call/内存引用,则我们可以很轻松地将
6A 30                    push 30h
改成
68 90 00 00 00           push 90h
,见

请注意图中红色框部分,和绿色圈部分与前图的区别

本人Q:2003255,加的时候请注明“看雪”。因本人经常写程序,所以不会做到天天上Q,请理解。

附件 patchme.rar


[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

上传的附件:
收藏
免费 7
支持
分享
最新回复 (72)
雪    币: 236
活跃值: (20)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
外挂攻防。无止境的较量
2010-2-1 06:27
0
雪    币: 73
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
wil
3
希望么123123
2010-2-1 09:59
0
雪    币: 1491
活跃值: (985)
能力值: (RANK:860 )
在线值:
发帖
回帖
粉丝
4
强烈支持,好文章啊
2010-2-1 11:16
0
雪    币: 375
活跃值: (201)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
牛人 膜拜一下
2010-2-1 12:37
0
雪    币: 339
活跃值: (1510)
能力值: ( LV13,RANK:970 )
在线值:
发帖
回帖
粉丝
6
轻则受到攻击后Server崩溃,重则被精心构造的ShellCode执行了恶意操作,例如添加个超级用户之类的,死都不知道是怎么死的。

我觉得黑客拿不到server,应该不会构造这么彪悍的溢出;

其次LZ为什么留QQ呢?

看楼主的做法是优化原exe程序,空出来的多余空间添加你自己的汇编代码,达到zeroadd,这样没什么意义吧?服务器硬盘又不是手机卡,省那点空间没啥意义的,何况你的“优化”可能会导致原程序出问题;

游戏server都加np了,我感觉这没什么必要,既然server已经往外传了(你都能拿到),我觉得你可以建议游戏公司在server端去掉np,一方面节省费用,一方面提高资源利用率;

你目前的工作貌似只解决了第6个问题,个人感觉前面的“致命问题”如果都这么处理,显然任重道远。个人提出以下思路:

前提:

在server端写个dll注入进去,方便对其进行修改,即比你修改反汇编简单,又能直接上高级语言;

问题1处理方法:

     可以找到server处理recv数据的地方,如果有明显的bug,直接修复之;如果找不到此类所在,在自己的dll中提前对数据长度进行检测,发现异常数据直接丢弃;

问题2处理方法:

     反外挂问题不是简单几步能搞好的,你有以下选择:1、找到成熟可靠的反外挂套路,放弃np,用新套路;2、在np基础上进行反外挂。分析外挂数据与正常游戏的不同,可以在服务器检测异常数据;

问题3处理方法:

     客户端的保护是无法防止游戏穿墙的,你所做的只有一条道路:在server处检测客户端数据流,对所有走路数据进行检查坐标点,发现异常则清退。这可能会有很大的资源消耗,所以我建议检测不必是实时检测,每隔一定时间查一次,可以极大减低资源消耗;

问题4处理方法:

     可以对你说的那个标记进行同步,也可以对server的装备处理加锁,防止同时修改数据。不过这要看服务器的具体实现了;

问题5处理方法:

     网络容错能力差一般在于2点:1、可能是心跳同步数据太频繁;2、异常数据检测太严,每个数据包内可能都有校验值,一旦发现校验出错马上断开。如果是第一种情况,可以降低心跳频率,实在不行去掉心跳,用connect断开作为掉线检测;如果是第二种情况,把每个封包内的数据校验去掉,或者作为掉线辅助判断。
2010-2-1 13:17
0
雪    币: 178
活跃值: (159)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
7
同问,呵呵,感觉关键的点都没怎么说,可能是保密需要,不过既然是保密需要,为啥要留qq?
2010-2-1 13:21
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
绝对的牛人啊,幸亏你是正方,如果在黑方,那棒子的游戏公司早被你给XX了,呵呵
2010-2-1 13:22
0
雪    币: 258
活跃值: (10)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
9
来这坛子就是为了交流。如果有同道,方便交流。本人不常上论坛,也不常上Q,如果通过论坛短信找我要Q,需要等几天,通过Q找我,又需要等几天,所以直接留Q
2010-2-1 13:33
0
雪    币: 258
活跃值: (10)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
10
拿不到Server的bin程序,也能让Server崩溃,这点不用怀疑。
我说的(轻则。。。重则。。。),是从逻辑上表示问题的严重性,并不表示一定能发生或容易发生。
2010-2-1 13:39
0
雪    币: 258
活跃值: (10)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
11
谢谢你的关心,不过我发现你还是没仔细看我的文章,可能是我的文章写得还不够好。
1:谢谢你对那6个问题所提出的自己的观点。可见你在这些方面也有相当深的研究。
2:window上可执行程序是exe/com/dll/sys,PE结构,linux上文件扩展名没有强制要求,文件结构也不是PE,是ELF结构。
3:我解决了6个问题,不是只解决了第6个问题。有些问题不是孤立的,是有联系的。
另外,我对这些程序的改动,不是像你想象的那样,用UltraEdit逐个字节写入,那样太累,所以你建议我用高级语言写程序,直接hook在关键点。

谢谢你的建议,但是我有更好的方法:
我对bin的改进,是自己写了个程序,能自动将我写的汇编代码,直接嵌入到合适的位置(该增的增,该改的改,该删的删,该跳的跳),这也相当于用高级语言写程序一样的方便,而我又能将目标程序的汇编优化整理出足够的空间,所以完全没有必要另外写个拖泥带水的程序。

如果用UltraEdit逐个字节加入,当修改规模大到一定程度的时候,会出现以下问题:
1:在我们尝试修正的时候,我们很难控制各个测试版本是否会混乱。
2:假设A bug的修正集合是改动了5处,B bug的修正集合是改动了6处,显然,在不断的尝试中,我们会因为这些修正的组合错误或改动点的不小心错误,带来更大的问题。
3:可能因为修正A bug引入A+ bug,

而我采用自己写个程序,能自动修改PE/ELF文件,自动嵌入汇编代码的方式,能从高级语言的视角去看整体的改进,所以即使改动很大,从思维上也能控制整个程序的改进,不会版本错乱,而且降低修正某bug带来新bug的可能性
2010-2-1 13:51
0
雪    币: 339
活跃值: (1510)
能力值: ( LV13,RANK:970 )
在线值:
发帖
回帖
粉丝
12
从你文章里仍然看不到前面5点问题的处理方法。

不过如果能实现你说的那个高级视角上的汇编代码修改,是比较牛的。佩服一下。
2010-2-1 14:47
0
雪    币: 339
活跃值: (1510)
能力值: ( LV13,RANK:970 )
在线值:
发帖
回帖
粉丝
13
拿不到server情况下让server崩溃这个我绝对承认,但如果拿不到server仍能搞个shellcode过去拿到权限,这就比较深邃了,没听说过这么高级的人物。
2010-2-1 14:48
0
雪    币: 339
活跃值: (1510)
能力值: ( LV13,RANK:970 )
在线值:
发帖
回帖
粉丝
14
你说你改改汇编码就完成那些问题了,我觉得还是有点诡异。

别的不说,光说那个穿墙加速吧。

穿墙加速问题的处理肯定在服务器,客户端是没用的。

要对付穿墙,你肯定要检测障碍,检测障碍首先就是个麻烦事,理想情况下,你要读取障碍图,对获取到的移动坐标点进行障碍判断,如果是3D地图,更麻烦了,不过你的xw貌似是2D的,这倒问题不大。你就算不采用检测数据流的办法,也要去读取数据库,也是个麻烦事;

其次是加速,判断加速要判断移动距离和时间,考虑到网络间隔,几个不同时段的数据会同时涌入的情况,你要加大时间间隔判断,这也是麻烦事。

这些东西我不是说无法实现或者是实现多复杂,但你说的改改二进制就行了,也太诡异了,调试一周+修改一周搞出来,再处理bug,我觉得光这个功能就起码半个月。你说你用工具改改几下就行了,是不是有点夸大其辞了?
2010-2-1 14:54
0
雪    币: 258
活跃值: (10)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
15
韩国开发团队的软件工程效率很高,政 府也出面组织引擎共享,代码复用,所以,如果你逆向了多个韩国游戏,你会发现他们的代码复用率很高,当然,正如我们调侃某人考试作弊一样:“你抄就抄了,怎么把别人名字也写在自己考卷上了?”是的,多数韩国游戏连bug都很相似。

看完我之前说的这句话,你应该有思路了吧?不好意思,不能说太细了。
2010-2-1 14:54
0
雪    币: 258
活跃值: (10)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
16
20年前,我听说牛人把游戏改了,从最后1关开始打,倒着打到第一关,也以为是不可能实现的事情。
你可能觉得我的文章没贴出大段的汇编不过瘾,但你不觉得我文章的思路比大段汇编更有意义吗?
有些Idea,不是我1个人的,况且我要保护我客户的利益,所以我不可能贴出具体汇编或具体解决方法。不用激将,我有原则。

而且我也没说这个项目做了多长时间完成。我更没有说“用工具改改几下就行了”。不知道是不是你搞错了?我通篇都没说这个任务很轻松,恰恰相反,我说了需要改动的地方太多,如果用UltraEdit手工改,很累,所以我自己写了工具,提高效率。提供1个思维与大家共享。

有时候,换个思维思考问题,我们不能仅仅满足于现有的现成的一些工具,像IDA,OD,SoftICE,ExeScope,ImportREC。
其实,用工具的人,和写工具的人视野是完全不一样的。
当我们自己会写这些工具的时候,你会发现有很多“不可能完成的任务”也有可能完成了。
2010-2-1 15:02
0
雪    币: 339
活跃值: (1510)
能力值: ( LV13,RANK:970 )
在线值:
发帖
回帖
粉丝
17
我一点也不觉得那大段汇编对我有哪怕一点的作用和吸引力,你要这么认为的话我没啥好说的了。
2010-2-1 16:11
0
雪    币: 205
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
18
应该是个精品的文章,呵呵,楼上的朋友,楼主主要表达的是解决的思路。
2010-2-1 16:24
0
雪    币: 178
活跃值: (159)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
19
对楼主的那个工具比较的好奇~
2010-2-1 16:26
0
雪    币: 258
活跃值: (10)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
20
你可能觉得“改改二进制”,改不出什么名堂,不能加太多功能进去,所以觉得要么是我夸大了bug,要么就是在吹牛,没能力改那么多地方。
根据我程序的统计,每个函数精简后,可以cut掉4%到16%不等的大小。假设文件为2M呢,3M呢?你想想看,能不能实现复杂功能,够不够实现?
希望本案例能改变你的思路。
2010-2-1 17:10
0
雪    币: 339
活跃值: (1510)
能力值: ( LV13,RANK:970 )
在线值:
发帖
回帖
粉丝
21
那的确是比较牛的,佩服。
2010-2-1 18:46
0
雪    币: 195
活跃值: (2249)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
22
不会是4f吧
正常来说开发公司只充许你提交bug然后等待他们修复
做为代理公司是不充许修改服务器程序的
2010-2-1 19:10
0
雪    币: 258
活跃值: (10)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
23
X是个韩国游戏,得过很多奖项,据公开资料,其几年前的代理费为500万美元。韩国开发团队的软件工程效率很高,政 府也出面组织引擎共享,代码复用,所以,如果你逆向了多个韩国游戏,你会发现他们的代码复用率很高,当然,正如我们调侃某人考试作弊一样:“你抄就抄了,怎么把别人名字也写在自己考卷上了?”是的,多数韩国游戏连bug都很相似。

从他们代码复用的角度来说,有些bug,是他们这些软件工程中的蓝领工人解决不了的,已经超出了他们知识范畴了。所以我们经常发现,韩国合作伙伴改bug的能力非常低,1个bug几年都改不了也是正常的。
2010-2-1 19:54
0
雪    币: 271
活跃值: (21)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
24
1:对指定bin程序(PE/ELF都可)中某Section一定范围内的汇编程序自动做优化调整。该删的删、该插的插,优化后的汇编指令直接向前靠,同时能修正相对jmp/call/内存引用

能做到这点太牛了,佩服LZ  虚函数也自动的吗?
2010-2-2 04:02
0
雪    币: 111
活跃值: (211)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
25
我猜只是针对函数挨个进行调整,如果整体代码处理感觉工作量挺大还容易失误
2010-2-2 08:33
0
游客
登录 | 注册 方可回帖
返回
//