我编写了一个游戏的外挂,这个游戏开始没有采用任何加密措施,后来开始采用HackShield来进行保护。
游戏最早采用的HS版本为4.0.0.47,后来升级到了4.2.0.7版本,但不知什么原因,在一个月后又回到了4.0.0.47版。前些天游戏又对HS进行了更新,目前最新版本为4.3.0.9。

4.0.0.47版与4.2.0.7版都采用的是ASProtect进行加密,而最新的4.3.0.9版则采用了Themida进行加密。

在这三个版本中我只对4.0.0.47版本进行了破解,采用的方法与大家通常采用的从驱动层进行破解的方式完全不同(我也不会...),而是从根本上停止了HS的运作。下面简单介绍一下4.0.0.47版的HS,以及我的破解方式。

4.0.0.47版EhSvc.dll函数功能表:
#1: Initialize
#2: StartService
#3: StopService
#4: UnInitialize
#8: PauseService
#9: ResumeService

#10:自校验,EAX为0表示通过
#12:获取内存、主执行文件和EhSvc.dll、EGRNAP.dll、EGRNAPX2.dll文件的HASH
#13:算法验证
#14:作用不明,EAX为0表示通过
#15:作用不明,似乎与14号函数成对运作

游戏主程序启动后会动态加载EhSvc.dll,然后调用1号函数初始化,之后调用10号函数对游戏主程序、EhSvc.dll、EGRNAP.dll及EGRNAPX2.dll等文件进行校验。检验成功后会调用2号函数启动HackShield服务,此时游戏进程进入保护状态。服务启动成功后,主程序调用14号函数,该函数的入口参数为一些主程序中的重要函数的地址。该函数的作用我没有搞清楚。
游戏运行过程中,服务器端会定时向客户端发送两条验证指令,游戏主程序在接收到这两条指令后会分别调用12号与13号函数对指令中夹带的数据进行算法处理,并由主程序将处理结果返回至服务器端,以达到验证客户端的目的。如果客户端不能在一段时间内返回数据或者返回了错误的数据,则服务器端会主动断开与客户端的连接。

由上面的分析可以看到,要想破解HS的保护,最关键的是要破解12号与13号函数的验证过程,无论对游戏主程序或HS本身做任何修改,都要保证这两个函数能返回正确的结果。

我首先对10号函数和2号函数进行了修改,使其始终返回执行成功,这样就可以使主程序运行在没有任何保护的状态下,可以对主程序进行调试分析。
经过逆向工程分析和调试分析,发现13号函数的功能非常简单,就是对由网络发来的数据进行算法处理,之后将处理结果返回服务器进行验证。这个函数与2号函数几乎没有任何交集,也就是说该函数的运作完全不依赖于HackShield服务。因此我很容易就破解了该函数,使其在不调用2号函数的前提下能够正常运作。
12号函数返回的也是算法处理的结果,但其结果中包含了内存与文件的HASH。其内存HASH所取的内存地址包含在网络包中,并且在一个包中包含有多个地址数据。文件HASH中则包含了对主程序和EhSvc.dll等文件的HASH处理。这个函数的运作也完全不依赖于HackShield服务。
为了解决内存HASH的问题,我采用了Hook方式,Hook了其内存访问函数,在Hook代码中对其要取数据的地址进行判断,如果位于主程序地址范围内,则伪造一片没有修改过的主程序内存映像,并将修改后的内存地址指针送入原内存访问函数,使HS获取伪造的内存数据。
对于文件HASH部分,则对主程序文件和EhSvc.dll文件分别处理。对于EhSvc.dll文件,由于HS访问该文件时都是采用文件名来指定文件,因此我保留的原始的EhSvc.dll文件,将修改后的文件命名为_EhSvc.dll然后修改主程序,使其加载修改后的文件,这样就解决了EhSvc.dll文件的HASH问题。HS在获取主程序的HASH时是通过GetModuleFileName函数获取的,因此我写了另一个Hook动态库,专门Hook该函数,使其返回结果指向原始的主程序文件。这样,12号函数也实现了脱离HackShield服务运行。

至此,12号与13号函数全部被破解,外挂与游戏均运行正常。

由以上破解过程可见,4.0.0.47版的EhSvc.dll在内部设计上存在严重缺陷,各函数与保护服务之间严重缺乏关联性,导致整个保护体系被轻易的破解。

4.2.0.7版与4.0.0.47版相比增加了一个验证函数,这个函数在计算HASH的过程中会与驱动程序进行通讯,因此上面的破解方法就不再适用了。

4.3.0.9版本更采用了Themida进行加密,函数个数也增加到了18个,以我的能力恐怕是搞不定了。

郁闷中......