奇迹Mu分析 - 封包协议

来源:互联网 发布:godaddy域名转入 编辑:程序博客网 时间:2024/04/29 11:06
1、游戏的主协议


所谓主协议也就是主要的协议类别,对于这款游戏来说可以分为4个类别它们的头分别是:

0xC1:

     * 常用于固定封包格式(例如:移动,NPC对话,使用物品,拾取,普通攻击 等等)

     * 特征:这类封包的长度一般较短

     * 包头结构如下:

_Buffer = Packed Record    Head:Byte;    //0xC1    Len:Byte;     //包长度end;

0xC2:

    * 常用于动态长度封包,常见于返回包(例如:怪物列表,背包列表,伤害包)

    * 特征:这类封包的长度一般较长

    *包头结构如下:

_Buffer = Packed Record    Head:Byte;    //0xC2    Len:Word;     //包长度end;

0xC3:

   *C1的二次加密包

0xC4:

   *C2的二次加密包


2、加密解密

大家看了上面的封包分析也发现了,这款游戏有2次加密,其实就是为了保护一些敏感的数据做的处理,其实后期游戏公司更加的猥琐了下,有部分发包有3次加密。

第一层加密:

这层加密最简单,一般就用于C1包的简单加密,下面就是逆向还原的算法

const   c_key :array [0..31] of byte = ($AB,$11,$CD,$FE,$18,$23,$C5,$A3,$CA,$33,                                  $C1,$CC,$66,$67,$21,$F3,$32,$12,$15,$35,                                  $29,$FF,$FE,$1D,$44,$EF,$CD,$41,$26,$3C,                                  $4E,$4D);  //加密 参数:IN OUT数据源, IN长度  返回:加密长度function MyEncode(Buffer: Pointer;Len: Integer): Integer;var  Src:pbyte;  i,j:Integer;  x:byte;begin  Src:=Buffer;  if Src^ = $C1 then    begin      Inc(Src);      Inc(Src);      x:=Src^;      Inc(Src);      for i := 3 to Len - 1 do        begin          j:=i and $8000001F;          Src^:=Src^ xor x xor c_key[j];          x:=Src^;          Inc(Src);        end;      Result:=Len;    end  else    Result:=-1;end;//解密  参数:IN OUT数据源, IN长度  返回:解密长度function MyDecode(Buffer: Pointer; Len: Integer): Integer;var  Src:array [0..100] of byte;  i:Integer;begin  CopyMemory(@Src,Buffer,Len);  if Src[0] = $C1 then    begin      for i := Len - 1 downto 3 do        begin          Src[i]:=Src[i] xor Src[i-1] xor c_key[i];        end;      Result:=Len;      CopyMemory(Buffer,@Src,Len);    end  else    Result:=-1;end;

第二层加密 :

即是C1完成加密后的变成C3的2次加密,由于加密过程被VM了,这里就提供下逆向片段

00605FFD   0F8D F3010000    JGE main.006061F600606003   33C0             XOR EAX,EAX00606005   0F85 EB010000    JNZ main.006061F60060600B   8B85 5CE3FDFF    MOV EAX,DWORD PTR SS:[EBP+FFFDE35C]00606011   40               INC EAX00606012   40               INC EAX00606013   8985 54CBFDFF    MOV DWORD PTR SS:[EBP+FFFDCB54],EAX00606019   C685 64FBFDFF C3 MOV BYTE PTR SS:[EBP+FFFDFB64],0C300606020   8A85 54CBFDFF    MOV AL,BYTE PTR SS:[EBP+FFFDCB54]00606026   8885 65FBFDFF    MOV BYTE PTR SS:[EBP+FFFDFB65],AL0060602C   8B85 0CCBFDFF    MOV EAX,DWORD PTR SS:[EBP+FFFDCB0C]00606032   2B85 58CBFDFF    SUB EAX,DWORD PTR SS:[EBP+FFFDCB58]00606038   50               PUSH EAX                                    //InLen     需要加密的长度00606039   8B85 58CBFDFF    MOV EAX,DWORD PTR SS:[EBP+FFFDCB58]0060603F   8D8405 5CCBFDFF  LEA EAX,DWORD PTR SS:[EBP+EAX+FFFDCB5C]00606046   50               PUSH EAX                                    //InBuffer  加密的数据源00606047   8D85 66FBFDFF    LEA EAX,DWORD PTR SS:[EBP+FFFDFB66]0060604D   50               PUSH EAX                                    //OutBuffer 加密后存放的缓存0060604E   FF35 5C2E2301    PUSH DWORD PTR DS:[1232E5C]              ;  //KeyTable  默认变量00606054   B9 1C6FBB08      MOV ECX,main.08BB6F1C                       //类指针00606059   E8 B28C4F00      CALL main.00AFED10                       ;  pC3EnCode 0060605E   A1 5C2E2301      MOV EAX,DWORD PTR DS:[1232E5C]00606063   8985 2CCBFDFF    MOV DWORD PTR SS:[EBP+FFFDCB2C],EAX00606069   8B85 54CBFDFF    MOV EAX,DWORD PTR SS:[EBP+FFFDCB54]0060606F   8985 38CBFDFF    MOV DWORD PTR SS:[EBP+FFFDCB38],EAX
这里给出这个函数的类型

Type   FEnCodeC3 = function (DefBase:Cardinal;OutBuffer:Pointer;InBuffer:Pointer;InLen:Integer):Integer;Stdcall;

第三层加密:

这个加密其实是基于1,2层中间的,是根据不同的包查询获得虚函数进行的加密,所以在这里提供一个查询的后调用虚函数的地方,给大家参考

00780522   E8 AC200000      CALL main.007825D300780527   0FB6C0           MOVZX EAX,AL0078052A   85C0             TEST EAX,EAX0078052C   74 02            JE SHORT main.007805300078052E   EB 1F            JMP SHORT main.0078054F00780530   8D4D F4          LEA ECX,DWORD PTR SS:[EBP-C]00780533   E8 76200000      CALL main.007825AE00780538   8B40 04          MOV EAX,DWORD PTR DS:[EAX+4]0078053B   8945 FC          MOV DWORD PTR SS:[EBP-4],EAX0078053E   FF75 10          PUSH DWORD PTR SS:[EBP+10]00780541   FF75 0C          PUSH DWORD PTR SS:[EBP+C]00780544   8B45 FC          MOV EAX,DWORD PTR SS:[EBP-4]00780547   8B00             MOV EAX,DWORD PTR DS:[EAX]00780549   8B4D FC          MOV ECX,DWORD PTR SS:[EBP-4]0078054C   FF50 04          CALL DWORD PTR DS:[EAX+4]               //这里就是查表后得到的3次加密处理0078054F   C9               LEAVE00780550   C2 0C00          RETN 0C00780553   55               PUSH EBP00780554   8BEC             MOV EBP,ESP00780556   83EC 18          SUB ESP,1800780559   894D E8          MOV DWORD PTR SS:[EBP-18],ECX0078055C   8D45 08          LEA EAX,DWORD PTR SS:[EBP+8]0078055F   50               PUSH EAX00780560   8D45 F4          LEA EAX,DWORD PTR SS:[EBP-C]00780563   50               PUSH EAX00780564   8B4D E8          MOV ECX,DWORD PTR SS:[EBP-18]
这里给出这个函数的通用类型

Type   FParamEncode = Procedure (var Buffer;Len:Integer);Stdcall;

3、返回包的分析

这款游戏的返回包中C1,C2头的是明文数据,没有任何加密,C3和C4则是2次加密。返回包中没有用到第3次加密!返回包是以粘连方式返回,如果HOOK Api Recv需自行拆分封包。




0 0
原创粉丝点击