六、加密的原理及解密

1、简单的加密解密例子

  • CS1.6人物速度加密实现

首先,找到人物速度后,访问速度查看任何改写和访问的代码。

document_image_rId4

然后对这四条都进行自实现简单的加解密。

document_image_rId5

进行HOOK。

document_image_rId6

效果如下:

加密前

document_image_rId7

加密后

document_image_rId8

  • 定位解密

访问速度。

document_image_rId9

根据自写代码可知,赋值为加密操作,读值为解密操作。因此查看取值代码。

document_image_rId10

根据游戏代码解密即可。

  • 结论

用到的加密数据附近必定有解密代码。

2、PUBG解密

  • Uworld

利用字符串SeamlessTravel FlushLevelStreaming定位到代码如下:

document_image_rId11

根据官方源码可知,Uworld在附近,但是这里看到是一个CALL,因此交叉引用后分析外层,得到下图结果。

document_image_rId12

可知Uworld来自(_QWORD *)(v1 + 160),但是这里并不是一个全局变量。看到上边sub_7FF77B03EE38有对v1+160操作,因此进去看看。

document_image_rId13

发现代码调用了off_7FF77E5E7720对a2,也就是Uworld进行了处理,下边又调用了off_7FF77E5E7728对处理后的数据进行二次处理。由于该处是UE4引擎对Uworld的初始化,但是游戏本身对Uworld有加密操作。因此变量qword_7FF77F9D96E0Uworld,函数off_7FF77E5E7720为加密函数,用于将加密后的数据赋值给Uworld,又因为此处需要用到Uworld,所以游戏又给他解密了,off_7FF77E5E7728为解密函数。为啥不直接用a2?别问,问就是不懂。

  • GName

利用字符串ByteProperty定位到代码如下:

document_image_rId14

从函数sub_7FF778C03450开始分析

document_image_rId15

可以看到a2 / 0x40F0,根据算法可以判定为0x40F0Chunk_Size,而且这里应该是在计算类名。既然计算了类名,那么肯定是需要GName,看到代码对a1进行了解密,并且看到将v3(就是除法计算好的结构) * 8加上 一个解密结果,所以可知a1是GName(Gname算法),追a1。

document_image_rId16

v2(也就是a1),被v1解密了一次,v1又从sub_7FF778C03830来,所以去这个函数里即可拿到GName。

document_image_rId17

  • GObject、Index

利用字符串DebugCanvasObject定位到代码如下:

document_image_rId18

很明显的一句v7 = off_7FF77DFDA628(1212074649i64, qword_7FF77F9988A8) + 0x30i64 * v11;,0x30是FObjectItem的结构大小,v11就相当于遍历的i(0~9999),这里是在获取GObject中的某一个对象。根据UObject成员可知,index为对象下标,所以Index的偏移为0x34,解密代码为:v17 ^ (v17 << 16) ^ 0xFC17596F

  • Class、Outer、FName

利用字符串CopyPropertiesForUnrelatedObjects定位到代码如下:

document_image_rId19

对应官方代码为:

document_image_rId20

由于GetFullName有获取Class,Outer,FName的成员,因此进入该函数寻找解密和偏移。

document_image_rId21

document_image_rId22

对比源代码分析后得到如下结果。

document_image_rId23

document_image_rId24