罗萨 发表于 2020-3-30 13:10

【VMP SDK+程序自校验+网络验证算法分析】某游戏辅助思路

本帖最后由 罗萨 于 2020-3-30 15:10 编辑

前言
   楼主近期分析某游戏辅助时,发现该辅助无壳并使用了VMP SDK加密了代码,同时具有自校验及序列号网络验证.由于楼主有一个真码,这对接下来的分析提供了很大帮助。难度并不大,先看分析,正文在后面.注:该软件使用的VMP SDK很鸡肋,可有可无的东西.
         软件下载地址:https://www.lanzouj.com/iashpje
准备工作
   使用到的软件有OD、SRSniffer、IDA、VMProtect_Ultimate_v3.3.03
   楼主使用的OD:https://www.lanzouj.com/iasngyb
   由于软件目录下有一个VMProtectSDK32.dll 文件,推测软件使用了VMPSDK加密了某些代码,关于这个SDK大家可以自行搜索一下相关资料,楼主这里使用VMProtect_Ultimate_v3.3.0打开主程序发现该软件使用了VMProtecBegin函数加密了某些代码,并且该软件没有使用VMP授权系统。
软件原理分析
   由于软件是TW软件,打开后会有乱码,启动这个软件后呢,如果序列号是经过了验证呢,左上角0/0/0这里会显示当天的时间。并且启动游戏后会注入DLL到游戏内,如果是真码会正确加载DLL,如果是假码会直接闪退游戏。该过程除了左上角的时间外无任何提示,并且DLL无法单独调试,所以该时间或许会是我们突破的关键点,我们先从这里入手。

程序自校验
   1、关于程序自校验有很多种方法,文件MD5、文件时间、关键字代码检测等,我们先随便修改一句代码看看。

   2、首先使用OD打开真码软件,楼主将入口点nop掉之后,打开发现注入失败,游戏闪退,那么我们首先要解决掉自校验的问题。
   3、这里我使用的是CreateFileA断点,程序断下来之后,右下角堆栈窗口显示调用的 "\\.\PhysicalDrive0",这应该是调用的管道,我们这里用不到,F9几次之后右下角出现了我们的文件名,这时在堆栈窗口光标处右键--反汇编窗口中跟随后就返回到了我们的代码段。


   4、上方的WriteCheck,说明这里是使用了VMPSDK保护的代码(之前在VMP软件内可以看到)WriteCheck字符串是加密标志,代码以VMProtecBegin函数开始并以VMProtecEnd为结束.
   5、拖到IDA跳转到代码地址,F5之后可以看到该代码段C伪代码.

   6、由于代码经过保护了了,我们在OD中在段首下断点重新运行之后,继续单步跟踪,发现程序会读取文件时间,以及一串类似md5码,0402321这里应该就是验证的关键字符串,我们对比未修改程序后发现该字符串果然不一样,将未修改程序的字符串记录下来.

修改之后的程序:ASCII "3c9730ec06ab264ab531ef0a536da1c9"

未修改程序:ASCII "b3384d3b4d7e5189662e64edddab7ee4"
   7、我们只要在
   00402321    lea edx,dword ptr ss:
   这一句代码之前将指向的数据修改为未修改程序的字符串就可以.随便找到一段空的代码段,我这里用的是0040F630,先将00402321这里的代码复制一下保存下来,并且记录一下一会将要返回的地址:00402326
   00402321   lea edx,dword ptr ss:
   00402325   push edx         

   将以上代码修改为 JMP0040F630.跟到0040F630后就开始修改我们的数据了.
                  ASCII "b3384d3b4d7e5189662e64edddab7ee4",该字符串的HEX为
   62 33 33 38
   34 64 33 62
   34 64 37 65
   35 31 38 39
   36 36 32 65
   36 34 65 64
   64 64 61 62
   37 65 65 34   
   修补的代码为:   
   mov dword ptr ss:,0x38333362
   mov dword ptr ss:,0x62336434
   mov dword ptr ss:,0x65376434
   mov dword ptr ss:,0x39383135
   mov dword ptr ss:,0x65323636
   mov dword ptr ss:,0x64653436
   mov dword ptr ss:,0x62616464
   mov dword ptr ss:,0x34656537
   lea edx,dword ptr ss:
   push edx                              
   jmp unpack1.00402326

   要注意的是,使用mov指令向地址写数据时要反着写,并且每次只能写入4字节,自行用计算器算一下指针,即要相加的值.后面两句是原地址的代码以及要返回的地址.保存所有修改之后再次打开程序后发现软件可以正常使用了.


楼下更新网络验证.


罗萨 发表于 2020-3-30 13:46

网络验证机制
   他的网络验证是这样:将本机序列号发送给服务器,如果序列号可以使用会返回一串加密后的数据,这个数据解密后就是软件左上角显示的时间(也就是当天),再次将这串字符串发送给服务器,服务器就会返回软件代码,才可以正常使用注入的DLL.如果序列号不可用,服务器就会返回0/0/0加密后的字符串并且不会返回正确的软件代码.那么我们只要将当天时间(格式为年/月/日)加密后发送给服务器那么这样就可以达到破解的目的了,但是加密算法只保存在服务器,所以我们可以找到解密算法后自己写一个加密算法发送给服务器.
找到解密算法
      下断bp send,还是像刚才那样返回到代码段首004026D0

刚才说过服务器会返回一段加密后的时间数据,那么解密算法就在后面这一大段代码当中了,用IDA载入后F5,可以看到一系列send recv的操作

慢慢跟踪调试,用OD下send或者recv断点调试的话会陷入死循环,所以我们尽量下载CALL指令上,在IDA中以sub_XXXX显示.调试几次后发现调用CALL 405AC0之后加密的字符串就变成了2020/3/30这样的时间格式,因为我是有真码所以会显示时间,假码的话会显示0/0/0

好只要我们在他解密前将字符串修改为我们自行加密后的数据就可以了.记录一下这个地址一会要用到.我们得先解决算法问题

罗萨 发表于 2020-3-30 13:50

本帖最后由 罗萨 于 2020-3-30 14:28 编辑

解密算法分析
         在IDA进入到刚才的CALL405AC0后我们就可以看到解密算法了.可能分析的比较模糊,有能力的朋友可以发一下清晰点的注释
// 算法使用两个参数,a1为加密前的字符串,a2为字符串指针
// 以"0/0/0"为例,这里的a1数据为"GIHHCWDACW"
int __stdcall sub_405AC0(const char *a1, int a2)
{
signed int v2; // esi
signed int v3; // ebp
char v4; // al
char v5; // dl
char v6; // dl
char v7; // al
char v8; // cl
int v9; // eax
int v10; // ecx
signed int v11; // ebp
int result; // eax
_BYTE *v13; // esi
int v14; // edi
int v15; // edi
char v16; // dl
int v17; //

v2 = 0;
v3 = strlen(a1);                              // 获取字符串的长度,结果保存在v3
if ( v3 > 0 )
{
    do
    {
      a1 -= 17;                           // 将前两个字符-11u,并且保存结果为ascii格式,例如:
                                                // 47 49,这两个字符-11u后为36 38,转换为ascii就是68
      v4 = a1 - 17;
      a1 = v4;
      v5 = a1;
      if ( (unsigned __int8)v5 <= 0x39u )       // 将前两个字符-11u后判断是否小等于39u,为真的话就-30u,假的话-37u
      v6 = v5 - 48;                           // 结果保存在其他地方,这两个判断的操作用不到
      else
      v6 = v5 - 55;
      if ( (unsigned __int8)v4 <= 0x39u )
      v7 = v4 - 48;
      else
      v7 = v4 - 55;
      v8 = v7 + 16 * v6;
      v9 = v2 / 2;
      v2 += 2;                                  // 每次操作两个字节
      *(_BYTE *)(v9 + a2) = v8;
    }
    while ( v2 < v3 );                        // 以"GIHHCWDACW"为例.执行完之后结果为"68772F302F",对应的ascii码为"hw/0/"
}
v10 = a2;
v11 = v3 >> 1;                              // 获取新的字符串长度,这里为5
result = v11 - 1;
*(_BYTE *)(a2 + v11) = 0;
if ( v11 - 1 >= 0 )
{
    v13 = (_BYTE *)(result + a2);
    v14 = 1 - a2;
    v17 = v11;
    while ( 1 )
    {
      v15 = (int)&v13;
      v16 = *(_BYTE *)((v15 + 2) % v11 + v10) ^ *v13;
      *v13 = v16;
      *v13-- = v16 ^ *(_BYTE *)(v15 % v11 + v10) ^ 0x58;
      result = v17 - 1;
      v17 = result;
      if ( !result )
      break;
      v14 = 1 - v10;
    }
}
return result;}

罗萨 发表于 2020-3-30 15:01

修改网络验证数据

我们可以看到算法上方这个esp指针保存的就是服务器返回的时间字符串,按照之前修改自校验那个方法修改这里就可以达到过网络校验的目的了,保存后运行游戏也没问题

罗萨 发表于 2020-3-30 15:04

运行效果

假码一样可以完美运行,没毛病老铁奥里给

那年夏天52 发表于 2020-3-30 13:15

谢谢分享

Fasy丶逝言 发表于 2020-3-30 13:18

这也太牛逼了{:1_889:}

tony666 发表于 2020-3-30 13:31

感谢分享,学习一下

大萌的微信 发表于 2020-3-30 13:40

感觉很牛批

赤座灯里 发表于 2020-3-30 13:45

要是个个辅助都有这个觉悟就好了:lol事实上你想不到他们有多变态{:1_909:}

罗萨 发表于 2020-3-30 13:47

赤座灯里 发表于 2020-3-30 13:45
要是个个辅助都有这个觉悟就好了事实上你想不到他们有多变态

每个情况都不一样,这里只讲思路
页: [1] 2 3 4 5
查看完整版本: 【VMP SDK+程序自校验+网络验证算法分析】某游戏辅助思路