Reversing Ex700, Ex700Plus protocol crypt

Results 1 to 11 of 11
  1. #1
    NN - Nord & Noob mauka is online now
    MemberRank
    Jul 2004 Join Date
    1,735Posts

    Reversing Ex700, Ex700Plus protocol crypt

    I was about to reverse all switch and Crypt function, but then got fucking bored.

    here what i reversed from Ex700Plus crypt, its like 1/10 of all..
    Code:
    {*******************************************************}
    {                                                       }
    {       uKeys                                           }
    {                                                       }
    {       Copyright (C) 2012 6748222@gmail.com            }
    {                                                       }
    {*******************************************************}
    
    unit uEncDec;
    
    interface
    
    uses
      Winapi.Windows, System.SysUtils;
    
    type
     T2DWords = array [0 .. 1] of Dword;
     P2DWords = ^T2DWords;
    
     TWzKeys = array [0 .. 3, 0 .. 7] of DWORD;
    
    const
      BL3Key: array [0 .. 3] of DWORD = ($CC66B00C, $5C8C92EF, 0, 0);
    
      EncWZkeys8: TWzKeys =(
      ($39333034, $3D392519, $2A3F2613, $383F2E13, $2F3D0926, $071D190B, $3F2F0312, $1E3D0A26),
      ($1F0D3517, $2C3D1E32, $2B3F0E1E, $3D382623, $3436303A, $3B3D383C, $3E2C293D, $133F2C39),
      ($37172B2D, $332C1F39, $3F190B1A, $372F2B2C, $3B2E3125, $33331437, $263E1237, $0E3A2D31),
      ($033E1912, $3F261804, $172B1F05, $0F172C07, $271D1317, $353B190F, $2F0B3725, $3F3C263A));
    
      DecWZkeys8: TWzKeys =(
      ($0E3A2D31, $263E1237, $33331437, $3B2E3125, $372F2B2C, $3F190B1A, $332C1F39, $37172B2D),
      ($3F3C263A, $2F0B3725, $353B190F, $271D1317, $0F172C07, $172B1F05, $3F261804, $033E1912),
      ($1E3D0A26, $3F2F0312, $071D190B, $2F3D0926, $383F2E13, $2A3F2613, $3D392519, $39333034),
      ($133F2C39, $3E2C293D, $3B3D383C, $3436303A, $3D382623, $2B3F0E1E, $2C3D1E32, $1F0D3517));
    
    
      AKey: array [0 .. 127] of Dword = ($01010400, $00000000, $00010000, $01010404,
        $01010004, $00010404, $00000004, $00010000, $00000400, $01010400, $01010404,
        $00000400, $01000404, $01010004, $01000000, $00000004, $00000404, $01000400,
        $01000400, $00010400, $00010400, $01010000, $01010000, $01000404, $00010004,
        $01000004, $01000004, $00010004, $00000000, $00000404, $00010404, $01000000,
        $00010000, $01010404, $00000004, $01010000, $01010400, $01000000, $01000000,
        $00000400, $01010004, $00010000, $00010400, $01000004, $00000400, $00000004,
        $01000404, $00010404, $01010404, $00010004, $01010000, $01000404, $01000004,
        $00000404, $00010404, $01010400, $00000404, $01000400, $01000400, $00000000,
        $00010004, $00010400, $00000000, $01010004, $80108020, $80008000, $00008000,
        $00108020, $00100000, $00000020, $80100020, $80008020, $80000020, $80108020,
        $80108000, $80000000, $80008000, $00100000, $00000020, $80100020, $00108000,
        $00100020, $80008020, $00000000, $80000000, $00008000, $00108020, $80100000,
        $00100020, $80000020, $00000000, $00108000, $00008020, $80108000, $80100000,
        $00008020, $00000000, $00108020, $80100020, $00100000, $80008020, $80100000,
        $80108000, $00008000, $80100000, $80008000, $00000020, $80108020, $00108020,
        $00000020, $00008000, $80000000, $00008020, $80108000, $00100000, $80000020,
        $00100020, $80008020, $80000020, $00100020, $00108000, $00000000, $80008000,
        $00008020, $80000000, $80100020, $80108020, $00108000);
    
      AXor1: array [0 .. 127] of Dword = ($00000208, $08020200, $00000000,
        $08020008, $08000200, $00000000, $00020208, $08000200, $00020008, $08000008,
        $08000008, $00020000, $08020208, $00020008, $08020000, $00000208, $08000000,
        $00000008, $08020200, $00000200, $00020200, $08020000, $08020008, $00020208,
        $08000208, $00020200, $00020000, $08000208, $00000008, $08020208, $00000200,
        $08000000, $08020200, $08000000, $00020008, $00000208, $00020000, $08020200,
        $08000200, $00000000, $00000200, $00020008, $08020208, $08000200, $08000008,
        $00000200, $00000000, $08020008, $08000208, $00020000, $08000000, $08020208,
        $00000008, $00020208, $00020200, $08000008, $08020000, $08000208, $00000208,
        $08020000, $00020208, $00000008, $08020008, $00020200, $00802001, $00002081,
        $00002081, $00000080, $00802080, $00800081, $00800001, $00002001, $00000000,
        $00802000, $00802000, $00802081, $00000081, $00000000, $00800080, $00800001,
        $00000001, $00002000, $00800000, $00802001, $00000080, $00800000, $00002001,
        $00002080, $00800081, $00000001, $00002080, $00800080, $00002000, $00802080,
        $00802081, $00000081, $00800080, $00800001, $00802000, $00802081, $00000081,
        $00000000, $00000000, $00802000, $00002080, $00800080, $00800081, $00000001,
        $00802001, $00002081, $00002081, $00000080, $00802081, $00000081, $00000001,
        $00002000, $00800001, $00002001, $00802080, $00800081, $00002001, $00002080,
        $00800000, $00802001, $00000080, $00800000, $00002000, $00802080);
    
      AXor2: array [0 .. 127] of Dword = ($00000100, $02080100, $02080000,
        $42000100, $00080000, $00000100, $40000000, $02080000, $40080100, $00080000,
        $02000100, $40080100, $42000100, $42080000, $00080100, $40000000, $02000000,
        $40080000, $40080000, $00000000, $40000100, $42080100, $42080100, $02000100,
        $42080000, $40000100, $00000000, $42000000, $02080100, $02000000, $42000000,
        $00080100, $00080000, $42000100, $00000100, $02000000, $40000000, $02080000,
        $42000100, $40080100, $02000100, $40000000, $42080000, $02080100, $40080100,
        $00000100, $02000000, $42080000, $42080100, $00080100, $42000000, $42080100,
        $02080000, $00000000, $40080000, $42000000, $00080100, $02000100, $40000100,
        $00080000, $00000000, $40080000, $02080100, $40000100, $20000010, $20400000,
        $00004000, $20404010, $20400000, $00000010, $20404010, $00400000, $20004000,
        $00404010, $00400000, $20000010, $00400010, $20004000, $20000000, $00004010,
        $00000000, $00400010, $20004010, $00004000, $00404000, $20004010, $00000010,
        $20400010, $20400010, $00000000, $00404010, $20404000, $00004010, $00404000,
        $20404000, $20000000, $20004000, $00000010, $20400010, $00404000, $20404010,
        $00400000, $00004010, $20000010, $00400000, $20004000, $20000000, $00004010,
        $20000010, $20404010, $00404000, $20400000, $00404010, $20404000, $00000000,
        $20400010, $00000010, $00004000, $20400000, $00404010, $00004000, $00400010,
        $20004010, $00000000, $20404000, $20000000, $00400010, $20004010);
    
      AXor3: array [0 .. 63] of Dword = ($00200000, $04200002, $04000802, $00000000,
        $00000800, $04000802, $00200802, $04200800, $04200802, $00200000, $00000000,
        $04000002, $00000002, $04000000, $04200002, $00000802, $04000800, $00200802,
        $00200002, $04000800, $04000002, $04200000, $04200800, $00200002, $04200000,
        $00000800, $00000802, $04200802, $00200800, $00000002, $04000000, $00200800,
        $04000000, $00200800, $00200000, $04000802, $04000802, $04200002, $04200002,
        $00000002, $00200002, $04000000, $04000800, $00200000, $04200800, $00000802,
        $00200802, $04200800, $00000802, $04000002, $04200802, $04200000, $00200800,
        $00000000, $00000002, $04200802, $00000000, $00200802, $04200000, $00000800,
        $04000002, $04000800, $00000800, $00200002);
    
      BKey: array [0 .. 127] of Dword = ($80108020, $80008000, $00008000, $00108020,
        $00100000, $00000020, $80100020, $80008020, $80000020, $80108020, $80108000,
        $80000000, $80008000, $00100000, $00000020, $80100020, $00108000, $00100020,
        $80008020, $00000000, $80000000, $00008000, $00108020, $80100000, $00100020,
        $80000020, $00000000, $00108000, $00008020, $80108000, $80100000, $00008020,
        $00000000, $00108020, $80100020, $00100000, $80008020, $80100000, $80108000,
        $00008000, $80100000, $80008000, $00000020, $80108020, $00108020, $00000020,
        $00008000, $80000000, $00008020, $80108000, $00100000, $80000020, $00100020,
        $80008020, $80000020, $00100020, $00108000, $00000000, $80008000, $00008020,
        $80000000, $80100020, $80108020, $00108000, $00000208, $08020200, $00000000,
        $08020008, $08000200, $00000000, $00020208, $08000200, $00020008, $08000008,
        $08000008, $00020000, $08020208, $00020008, $08020000, $00000208, $08000000,
        $00000008, $08020200, $00000200, $00020200, $08020000, $08020008, $00020208,
        $08000208, $00020200, $00020000, $08000208, $00000008, $08020208, $00000200,
        $08000000, $08020200, $08000000, $00020008, $00000208, $00020000, $08020200,
        $08000200, $00000000, $00000200, $00020008, $08020208, $08000200, $08000008,
        $00000200, $00000000, $08020008, $08000208, $00020000, $08000000, $08020208,
        $00000008, $00020208, $00020200, $08000008, $08020000, $08000208, $00000208,
        $08020000, $00020208, $00000008, $08020008, $00020200);
    
      BXor1: array [0 .. 127] of Dword = ($00802001, $00002081, $00002081,
        $00000080, $00802080, $00800081, $00800001, $00002001, $00000000, $00802000,
        $00802000, $00802081, $00000081, $00000000, $00800080, $00800001, $00000001,
        $00002000, $00800000, $00802001, $00000080, $00800000, $00002001, $00002080,
        $00800081, $00000001, $00002080, $00800080, $00002000, $00802080, $00802081,
        $00000081, $00800080, $00800001, $00802000, $00802081, $00000081, $00000000,
        $00000000, $00802000, $00002080, $00800080, $00800081, $00000001, $00802001,
        $00002081, $00002081, $00000080, $00802081, $00000081, $00000001, $00002000,
        $00800001, $00002001, $00802080, $00800081, $00002001, $00002080, $00800000,
        $00802001, $00000080, $00800000, $00002000, $00802080, $00000100, $02080100,
        $02080000, $42000100, $00080000, $00000100, $40000000, $02080000, $40080100,
        $00080000, $02000100, $40080100, $42000100, $42080000, $00080100, $40000000,
        $02000000, $40080000, $40080000, $00000000, $40000100, $42080100, $42080100,
        $02000100, $42080000, $40000100, $00000000, $42000000, $02080100, $02000000,
        $42000000, $00080100, $00080000, $42000100, $00000100, $02000000, $40000000,
        $02080000, $42000100, $40080100, $02000100, $40000000, $42080000, $02080100,
        $40080100, $00000100, $02000000, $42080000, $42080100, $00080100, $42000000,
        $42080100, $02080000, $00000000, $40080000, $42000000, $00080100, $02000100,
        $40000100, $00080000, $00000000, $40080000, $02080100, $40000100);
    
      BXor2: array [0 .. 127] of Dword = ($20000010, $20400000, $00004000,
        $20404010, $20400000, $00000010, $20404010, $00400000, $20004000, $00404010,
        $00400000, $20000010, $00400010, $20004000, $20000000, $00004010, $00000000,
        $00400010, $20004010, $00004000, $00404000, $20004010, $00000010, $20400010,
        $20400010, $00000000, $00404010, $20404000, $00004010, $00404000, $20404000,
        $20000000, $20004000, $00000010, $20400010, $00404000, $20404010, $00400000,
        $00004010, $20000010, $00400000, $20004000, $20000000, $00004010, $20000010,
        $20404010, $00404000, $20400000, $00404010, $20404000, $00000000, $20400010,
        $00000010, $00004000, $20400000, $00404010, $00004000, $00400010, $20004010,
        $00000000, $20404000, $20000000, $00400010, $20004010, $00200000, $04200002,
        $04000802, $00000000, $00000800, $04000802, $00200802, $04200800, $04200802,
        $00200000, $00000000, $04000002, $00000002, $04000000, $04200002, $00000802,
        $04000800, $00200802, $00200002, $04000800, $04000002, $04200000, $04200800,
        $00200002, $04200000, $00000800, $00000802, $04200802, $00200800, $00000002,
        $04000000, $00200800, $04000000, $00200800, $00200000, $04000802, $04000802,
        $04200002, $04200002, $00000002, $00200002, $04000000, $04000800, $00200000,
        $04200800, $00000802, $00200802, $04200800, $00000802, $04000002, $04200802,
        $04200000, $00200800, $00000000, $00000002, $04200802, $00000000, $00200802,
        $04200000, $00000800, $04000002, $04000800, $00000800, $00200002);
    
      BXor3: array [0 .. 63] of Dword = ($10001040, $00001000, $00040000, $10041040,
        $10000000, $10001040, $00000040, $10000000, $00040040, $10040000, $10041040,
        $00041000, $10041000, $00041040, $00001000, $00000040, $10040000, $10000040,
        $10001000, $00001040, $00041000, $00040040, $10040040, $10041000, $00001040,
        $00000000, $00000000, $10040040, $10000040, $10001000, $00041040, $00040000,
        $00041040, $00040000, $10041000, $00001000, $00000040, $10040040, $00001000,
        $00041040, $10001000, $00000040, $10000040, $10040000, $10040040, $10000000,
        $00040000, $10001040, $00000000, $10041040, $00040040, $10000040, $10040000,
        $10001000, $10001040, $00000000, $10041040, $00041000, $00041000, $00001040,
        $00001040, $00040040, $10000000, $10041000);
    
      CKey: array [0 .. 127] of Dword = ($01010400, $00000000, $00010000, $01010404,
        $01010004, $00010404, $00000004, $00010000, $00000400, $01010400, $01010404,
        $00000400, $01000404, $01010004, $01000000, $00000004, $00000404, $01000400,
        $01000400, $00010400, $00010400, $01010000, $01010000, $01000404, $00010004,
        $01000004, $01000004, $00010004, $00000000, $00000404, $00010404, $01000000,
        $00010000, $01010404, $00000004, $01010000, $01010400, $01000000, $01000000,
        $00000400, $01010004, $00010000, $00010400, $01000004, $00000400, $00000004,
        $01000404, $00010404, $01010404, $00010004, $01010000, $01000404, $01000004,
        $00000404, $00010404, $01010400, $00000404, $01000400, $01000400, $00000000,
        $00010004, $00010400, $00000000, $01010004, $80108020, $80008000, $00008000,
        $00108020, $00100000, $00000020, $80100020, $80008020, $80000020, $80108020,
        $80108000, $80000000, $80008000, $00100000, $00000020, $80100020, $00108000,
        $00100020, $80008020, $00000000, $80000000, $00008000, $00108020, $80100000,
        $00100020, $80000020, $00000000, $00108000, $00008020, $80108000, $80100000,
        $00008020, $00000000, $00108020, $80100020, $00100000, $80008020, $80100000,
        $80108000, $00008000, $80100000, $80008000, $00000020, $80108020, $00108020,
        $00000020, $00008000, $80000000, $00008020, $80108000, $00100000, $80000020,
        $00100020, $80008020, $80000020, $00100020, $00108000, $00000000, $80008000,
        $00008020, $80000000, $80100020, $80108020, $00108000);
    
      CXor1: array [0 .. 127] of Dword = ($00000208, $08020200, $00000000,
        $08020008, $08000200, $00000000, $00020208, $08000200, $00020008, $08000008,
        $08000008, $00020000, $08020208, $00020008, $08020000, $00000208, $08000000,
        $00000008, $08020200, $00000200, $00020200, $08020000, $08020008, $00020208,
        $08000208, $00020200, $00020000, $08000208, $00000008, $08020208, $00000200,
        $08000000, $08020200, $08000000, $00020008, $00000208, $00020000, $08020200,
        $08000200, $00000000, $00000200, $00020008, $08020208, $08000200, $08000008,
        $00000200, $00000000, $08020008, $08000208, $00020000, $08000000, $08020208,
        $00000008, $00020208, $00020200, $08000008, $08020000, $08000208, $00000208,
        $08020000, $00020208, $00000008, $08020008, $00020200, $00802001, $00002081,
        $00002081, $00000080, $00802080, $00800081, $00800001, $00002001, $00000000,
        $00802000, $00802000, $00802081, $00000081, $00000000, $00800080, $00800001,
        $00000001, $00002000, $00800000, $00802001, $00000080, $00800000, $00002001,
        $00002080, $00800081, $00000001, $00002080, $00800080, $00002000, $00802080,
        $00802081, $00000081, $00800080, $00800001, $00802000, $00802081, $00000081,
        $00000000, $00000000, $00802000, $00002080, $00800080, $00800081, $00000001,
        $00802001, $00002081, $00002081, $00000080, $00802081, $00000081, $00000001,
        $00002000, $00800001, $00002001, $00802080, $00800081, $00002001, $00002080,
        $00800000, $00802001, $00000080, $00800000, $00002000, $00802080);
    
      CXor2: array [0 .. 127] of Dword = ($00000100, $02080100, $02080000,
        $42000100, $00080000, $00000100, $40000000, $02080000, $40080100, $00080000,
        $02000100, $40080100, $42000100, $42080000, $00080100, $40000000, $02000000,
        $40080000, $40080000, $00000000, $40000100, $42080100, $42080100, $02000100,
        $42080000, $40000100, $00000000, $42000000, $02080100, $02000000, $42000000,
        $00080100, $00080000, $42000100, $00000100, $02000000, $40000000, $02080000,
        $42000100, $40080100, $02000100, $40000000, $42080000, $02080100, $40080100,
        $00000100, $02000000, $42080000, $42080100, $00080100, $42000000, $42080100,
        $02080000, $00000000, $40080000, $42000000, $00080100, $02000100, $40000100,
        $00080000, $00000000, $40080000, $02080100, $40000100, $20000010, $20400000,
        $00004000, $20404010, $20400000, $00000010, $20404010, $00400000, $20004000,
        $00404010, $00400000, $20000010, $00400010, $20004000, $20000000, $00004010,
        $00000000, $00400010, $20004010, $00004000, $00404000, $20004010, $00000010,
        $20400010, $20400010, $00000000, $00404010, $20404000, $00004010, $00404000,
        $20404000, $20000000, $20004000, $00000010, $20400010, $00404000, $20404010,
        $00400000, $00004010, $20000010, $00400000, $20004000, $20000000, $00004010,
        $20000010, $20404010, $00404000, $20400000, $00404010, $20404000, $00000000,
        $20400010, $00000010, $00004000, $20400000, $00404010, $00004000, $00400010,
        $20004010, $00000000, $20404000, $20000000, $00400010, $20004010);
    
      CXor3: array [0 .. 63] of Dword = ($00200000, $04200002, $04000802, $00000000,
        $00000800, $04000802, $00200802, $04200800, $04200802, $00200000, $00000000,
        $04000002, $00000002, $04000000, $04200002, $00000802, $04000800, $00200802,
        $00200002, $04000800, $04000002, $04200000, $04200800, $00200002, $04200000,
        $00000800, $00000802, $04200802, $00200800, $00000002, $04000000, $00200800,
        $04000000, $00200800, $00200000, $04000802, $04000802, $04200002, $04200002,
        $00000002, $00200002, $04000000, $04000800, $00200000, $04200800, $00000802,
        $00200802, $04200800, $00000802, $04000002, $04200802, $04200000, $00200800,
        $00000000, $00000002, $04200802, $00000000, $00200802, $04200000, $00000800,
        $04000002, $04000800, $00000800, $00200002);
    
      DKey: array [0 .. 127] of Dword = ($80108020, $80008000, $00008000, $00108020,
        $00100000, $00000020, $80100020, $80008020, $80000020, $80108020, $80108000,
        $80000000, $80008000, $00100000, $00000020, $80100020, $00108000, $00100020,
        $80008020, $00000000, $80000000, $00008000, $00108020, $80100000, $00100020,
        $80000020, $00000000, $00108000, $00008020, $80108000, $80100000, $00008020,
        $00000000, $00108020, $80100020, $00100000, $80008020, $80100000, $80108000,
        $00008000, $80100000, $80008000, $00000020, $80108020, $00108020, $00000020,
        $00008000, $80000000, $00008020, $80108000, $00100000, $80000020, $00100020,
        $80008020, $80000020, $00100020, $00108000, $00000000, $80008000, $00008020,
        $80000000, $80100020, $80108020, $00108000, $00000208, $08020200, $00000000,
        $08020008, $08000200, $00000000, $00020208, $08000200, $00020008, $08000008,
        $08000008, $00020000, $08020208, $00020008, $08020000, $00000208, $08000000,
        $00000008, $08020200, $00000200, $00020200, $08020000, $08020008, $00020208,
        $08000208, $00020200, $00020000, $08000208, $00000008, $08020208, $00000200,
        $08000000, $08020200, $08000000, $00020008, $00000208, $00020000, $08020200,
        $08000200, $00000000, $00000200, $00020008, $08020208, $08000200, $08000008,
        $00000200, $00000000, $08020008, $08000208, $00020000, $08000000, $08020208,
        $00000008, $00020208, $00020200, $08000008, $08020000, $08000208, $00000208,
        $08020000, $00020208, $00000008, $08020008, $00020200);
    
      DXor1: array [0 .. 127] of Dword = ($00802001, $00002081, $00002081,
        $00000080, $00802080, $00800081, $00800001, $00002001, $00000000, $00802000,
        $00802000, $00802081, $00000081, $00000000, $00800080, $00800001, $00000001,
        $00002000, $00800000, $00802001, $00000080, $00800000, $00002001, $00002080,
        $00800081, $00000001, $00002080, $00800080, $00002000, $00802080, $00802081,
        $00000081, $00800080, $00800001, $00802000, $00802081, $00000081, $00000000,
        $00000000, $00802000, $00002080, $00800080, $00800081, $00000001, $00802001,
        $00002081, $00002081, $00000080, $00802081, $00000081, $00000001, $00002000,
        $00800001, $00002001, $00802080, $00800081, $00002001, $00002080, $00800000,
        $00802001, $00000080, $00800000, $00002000, $00802080, $00000100, $02080100,
        $02080000, $42000100, $00080000, $00000100, $40000000, $02080000, $40080100,
        $00080000, $02000100, $40080100, $42000100, $42080000, $00080100, $40000000,
        $02000000, $40080000, $40080000, $00000000, $40000100, $42080100, $42080100,
        $02000100, $42080000, $40000100, $00000000, $42000000, $02080100, $02000000,
        $42000000, $00080100, $00080000, $42000100, $00000100, $02000000, $40000000,
        $02080000, $42000100, $40080100, $02000100, $40000000, $42080000, $02080100,
        $40080100, $00000100, $02000000, $42080000, $42080100, $00080100, $42000000,
        $42080100, $02080000, $00000000, $40080000, $42000000, $00080100, $02000100,
        $40000100, $00080000, $00000000, $40080000, $02080100, $40000100);
    
      DXor2: array [0 .. 127] of Dword = ($20000010, $20400000, $00004000,
        $20404010, $20400000, $00000010, $20404010, $00400000, $20004000, $00404010,
        $00400000, $20000010, $00400010, $20004000, $20000000, $00004010, $00000000,
        $00400010, $20004010, $00004000, $00404000, $20004010, $00000010, $20400010,
        $20400010, $00000000, $00404010, $20404000, $00004010, $00404000, $20404000,
        $20000000, $20004000, $00000010, $20400010, $00404000, $20404010, $00400000,
        $00004010, $20000010, $00400000, $20004000, $20000000, $00004010, $20000010,
        $20404010, $00404000, $20400000, $00404010, $20404000, $00000000, $20400010,
        $00000010, $00004000, $20400000, $00404010, $00004000, $00400010, $20004010,
        $00000000, $20404000, $20000000, $00400010, $20004010, $00200000, $04200002,
        $04000802, $00000000, $00000800, $04000802, $00200802, $04200800, $04200802,
        $00200000, $00000000, $04000002, $00000002, $04000000, $04200002, $00000802,
        $04000800, $00200802, $00200002, $04000800, $04000002, $04200000, $04200800,
        $00200002, $04200000, $00000800, $00000802, $04200802, $00200800, $00000002,
        $04000000, $00200800, $04000000, $00200800, $00200000, $04000802, $04000802,
        $04200002, $04200002, $00000002, $00200002, $04000000, $04000800, $00200000,
        $04200800, $00000802, $00200802, $04200800, $00000802, $04000002, $04200802,
        $04200000, $00200800, $00000000, $00000002, $04200802, $00000000, $00200802,
        $04200000, $00000800, $04000002, $04000800, $00000800, $00200002);
    
      DXor3: array [0 .. 63] of Dword = ($10001040, $00001000, $00040000,
        $10041040, $10000000, $10001040, $00000040, $10000000, $00040040, $10040000,
        $10041040, $00041000, $10041000, $00041040, $00001000, $00000040, $10040000,
        $10000040, $10001000, $00001040, $00041000, $00040040, $10040040, $10041000,
        $00001040, $00000000, $00000000, $10040040, $10000040, $10001000, $00041040,
        $00040000, $00041040, $00040000, $10041000, $00001000, $00000040, $10040040,
        $00001000, $00041040, $10001000, $00000040, $10000040, $10040000, $10040040,
        $10000000, $00040000, $10001040, $00000000, $10041040, $00040040, $10000040,
        $10040000, $10001000, $10001040, $00000000, $10041040, $00041000, $00041000,
        $00001040, $00001040, $00040040, $10000000, $10041000);
    
    
      KeyByteC1C2: 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);
    
     LoginKeys: array [0..2] of Byte = ($FC, $CF, $AB);
    
    
     function DecryptC3C4(lpDest: Pointer; lpSource: Pointer; ToServer: Boolean): Integer;
     function EncryptC3C4(lpDest: Pointer; lpSource: Pointer; Counter: Byte; ToServer: Boolean): Integer;
    
     function EncodeIP(InVal: string): string;
     function EncodePort(Port: integer; IpLen: String):integer;
    
     procedure EncDecLogin(Data: PByteArray; Size: Integer);
     procedure DecodeC1(Data: PByteArray; HeaderSize, Length: Integer);
     procedure EncodeC1(Data: PByteArray; HeaderSize, Length: Integer);
     procedure _DecodeC1(DecryptResult, Data: PByteArray; HeaderSize, Length: Integer);
     procedure _EncodeC1(EncryptResult, Data: PByteArray; HeaderSize, Length: Integer);
    
    implementation
    
    function EncodeIP(InVal: string): string;
    var
      Position, I: Integer;
    begin
      Result := '';
      Position := 0;
      for I := 1 to Length(InVal) do
      begin
        Position := Position + 1;
        case Position of
          1: Result := Result + Chr(Ord(InVal[I]) + 12);
          2: Result := Result + Chr(Ord(InVal[I]) + 7);
          3: Result := Result + Chr(Ord(InVal[I]) + 3);
          4:
           begin
            Result := Result + Chr(Ord(InVal[I]) + 19);
            Position := 0;
           end;
        end;
      end;
    end;
    
    function EncodePort(Port: integer; IpLen: String):integer;
    var
     X: Integer;
     Tmp: Integer;
    begin
     Tmp := 0;
     X := Length(IpLen) mod 4;
      case X of
       0: Tmp := Port + 12 - Port div 4 mod 4 *8;
       1: Tmp := Port +  7 - Port mod 8 * 2;
       2: Tmp := Port +  3 - Port mod 4 * 2;
       3: Tmp := Port + 19 - Port mod 4 * 2 - Port div 16 mod 2 * 32;
      end;
     Result := Tmp;
    end;
    
    procedure EncDecLogin(Data: PByteArray; Size: Integer);
    var
     K: Integer;
    begin
     for K := 0 to (Size - 1) do
      Data[K] := Data[K] xor LoginKeys[K mod 3];
    end;
    
    
    
    function SwapDword(inKey: Dword): Dword;
    begin
     Result := ($FF000000 and (InKey shl 24)) or ($00FF0000 and (InKey shl 8))
            or ($0000FF00 and (InKey shr 8))  or ($000000FF and (InKey shr 24));
    end;
    
    function ROL(const value, shift: DWORD): DWORD;
    asm
     MOV ECX, EDX
     ROL EAX, CL
    end;
    
    function ROR(const value, shift: DWORD): DWORD;
    asm
     MOV ECX, EDX
     ROR EAX, CL
    end;
    
    procedure _DecodeC1(DecryptResult, Data: PByteArray; HeaderSize, Length: Integer);
    var
      K: Integer;
    begin
      for K := 0 to (Length - 1) do
        if (K <= 2) then
          DecryptResult[K] := Data[K + HeaderSize]
        else
          DecryptResult[K] := Data[K + HeaderSize] xor (Data[K - 1 + HeaderSize] xor KeyByteC1C2[K mod 32]);
    end;
    
    procedure _EncodeC1(EncryptResult, Data: PByteArray; HeaderSize, Length: Integer);
    var
      K: Integer;
    begin
      for K := 0 to (Length - 1) do
        if (K <= 2) then
          EncryptResult[K] := Data[K + HeaderSize]
        else
          EncryptResult[K] := Data[K + HeaderSize] xor (EncryptResult[K - 1 + HeaderSize] xor KeyByteC1C2[K mod 32]);
    end;
    
    
    procedure DecodeC1(Data: PByteArray; HeaderSize, Length: Integer);
    var
      I: Integer;
    begin
      for I := 0 to (Length - 1) do
        if (I <= 2) then
          Data[I] := Data[I + HeaderSize]
        else
          Data[I] := Data[I + HeaderSize] xor (Data[I - 1 + HeaderSize] xor KeyByteC1C2[I mod 32]);
    end;
    
    procedure EncodeC1(Data: PByteArray; HeaderSize, Length: Integer);
    var
      I: Integer;
    begin
      for I := 0 to (Length - 1) do
        if (I <= 2) then
          Data[I] := Data[I + HeaderSize]
        else
          Data[I] := Data[I + HeaderSize] xor (Data[I - 1 + HeaderSize] xor KeyByteC1C2[I mod 32]);
    end;
    
    
    function Enc2DWords(InArray: T2DWords): T2DWords;
    var
     TmpDword, TmpDword2, TmpDword3: DWORD;
     TmpDword4, TmpDword5: T2DWords;
    begin
     TmpDword4 := InArray;
     TmpDword5 := TmpDword4;
    
     TmpDword4[1] := ROL(TmpDword4[1], 4);
     TmpDword4[0] :=  (TmpDword4[0] xor TmpDword4[1]) and $F0F0F0F0;
    
     TmpDword5[0] := TmpDword5[0] xor TmpDword4[0];
     TmpDword4[1] := TmpDword4[1] xor TmpDword4[0];
     TmpDword4[1] := ROR(TmpDword4[1], $14);
    
     TmpDword := TmpDword4[1];
    
     TmpDword4[1] := (TmpDword xor TmpDword5[0]) and $FFFF0000;
     TmpDword5[0] := (TmpDword5[0] xor TmpDword4[1]);
    
     TmpDword := TmpDword xor TmpDword4[1];
     TmpDword := ROR(TmpDword, $12);
    
     TmpDword2 := TmpDword;
    
     TmpDword := (TmpDword xor TmpDword5[0]) and $33333333;
     TmpDword5[0] := TmpDword5[0] xor TmpDword;
    
     TmpDword2 := TmpDword2 xor TmpDword;
     TmpDword2 := ROR(TmpDword2, 6);
    
     TmpDword3 := TmpDword2;
    
     TmpDword2 := (TmpDWord2 xor TmpDWord5[0]) and $0FF00FF;
     TmpDWord5[0] := TmpDWord5[0] xor TmpDword2;
    
     TmpDword3 := TmpDword3 xor TmpDword2;
     TmpDword3 := ROL(TmpDword3, 9);
    
     Result[0] := TmpDword3;
    
     TmpDword3 := (TmpDword3 xor TmpDword5[0]) and $AAAAAAAA;
    
     Result[0] :=  Result[0] xor TmpDword3;
     TmpDword5[0] := TmpDword5[0] xor TmpDword3;
    
     Result[1] := ROL(TmpDword5[0], 1) // CD10BAA5
    end;
    
    function GenerateKeys(InDword: T2DWords; WZkeys: TWzKeys): T2DWords; //TmpResult
    var
     K: Integer;
     TmpDword, TmpDword2: DWORD;
     Keys: array [0 .. 3] of Dword;
    begin
     Result[0] := InDword[0]; //ESI=DAFA62F9
     Result[1] := InDword[1];
    
     for K := 0 to 7 do
      begin
       TmpDword := ROR(Result[0], 4) xor WZkeys[0, K];  //BDB1A69B
    
       Keys[0] := AKey[(TmpDword shr $18) and $3F];
       Keys[1] := AXor1[(TmpDword shr $10) and $3F];
       Keys[2] := AXor2[(TmpDword shr   8) and $3F];
       Keys[3] := AXor3[TmpDword and $3F];
    
    
       TmpDword := ((Keys[0] xor Keys[1]) xor Keys[2]) xor Keys[3];  //46230D02
       TmpDword2 := Result[1] xor TmpDword;      //<---   TE  2 -> 3B0BAF6E
    
       TmpDword := Result[0] xor WZkeys[1, K];   //<---
    
       Keys[0] := BKey[(TmpDword shr $18) and $3F];
       Keys[1] := BXor1[(TmpDword shr $10) and $3F];
       Keys[2] := BXor2[(TmpDword shr   8) and $3F];
       Keys[3] := BXor3[TmpDword and $3F];
    
       TmpDword := ((Keys[0] xor Keys[1]) xor Keys[2]) xor Keys[3];
       Result[1] := TmpDword2 xor TmpDword;     //<-- TE
    
       TmpDword := ROR(Result[1], 4) xor WZkeys[2, K];
    
       Keys[0] := CKey[(TmpDword shr $18) and $3F];
       Keys[1] := CXor1[(TmpDword shr $10) and $3F];
       Keys[2] := CXor2[(TmpDword shr   8) and $3F];
       Keys[3] := CXor3[TmpDword and $3F];
    
       TmpDword := ((Keys[0] xor Keys[1]) xor Keys[2]) xor Keys[3]; //03030700
       TmpDword2 := Result[0] xor TmpDword;  //<---   TE
    
       TmpDword := WZkeys[3, K] xor Result[1];
    
       Keys[0] := DKey[(TmpDword shr $18) and $3F];
       Keys[1] := DXor1[(TmpDword shr $10) and $3F];
       Keys[2] := DXor2[(TmpDword shr   8) and $3F];
       Keys[3] := DXor3[TmpDword and $3F];
    
       TmpDword := ((Keys[0] xor Keys[1]) xor Keys[2]) xor Keys[3];
       Result[0] := TmpDword2 xor TmpDword;  //<---  14D6C46A / 3745D33A / 9AA53C27 -> A0684984
      end;
    end;
    
    function Dec2DWords(InArray: T2DWords): T2DWords;  //Fuck this shit!!!!
    var
     TmpDword, TmpDword2, TmpDword3, A, B: DWORD;
     TmpDword4, TmpDword5: T2DWords;
    begin
     TmpDword5 := InArray;
     TmpDword4 := TmpDword5;
    
     TmpDword5[0] := ROR(TmpDword5[0], 1);
     TmpDword5[1] := (TmpDword5[1] xor TmpDword5[0]) and $AAAAAAAA;
     TmpDword3 := TmpDword5[1] xor TmpDword5[0];
    
     TmpDword := TmpDword3;
    
     TmpDword4[1] := TmpDword4[1] xor TmpDword5[1];
     TmpDword2 := ROR(TmpDword4[1], 9);
    
     TmpDword3 := (TmpDword3 xor TmpDword2) and $0FF00FF;
    
     TmpDword := TmpDword xor TmpDword3;
     TmpDword2 := TmpDword2 xor TmpDword3;
    
     Result[1] := ROL(TmpDword2, 6);
    
     TmpDword2 := (Result[1] xor TmpDword) and $33333333;
     TmpDword3 := TmpDword2 xor TmpDword;    //EDI=EB88BE12
    
     Result[1] := Result[1] xor TmpDword2;
    
     Result[1] := ROL(Result[1], $12);
    
     TmpDword2 := Result[1];
    
     Result[1] := (Result[1] xor TmpDword3) and $FFFF0000;
    
     TmpDword := TmpDword3 xor Result[1];
     TmpDword2 := TmpDword2 xor Result[1];
    
     A := TmpDword;
    
     TmpDword := ROL(TmpDword2, $14);
     B :=  TmpDword;
     TmpDword := (TmpDword xor A)  and $F0F0F0F0; // xor 2249BE12
    
     Result[0] := A xor TmpDword;    //<-- result to
    
     B := B xor TmpDword;
     Result[1] := ROR(B, 4);   //D2B4EB81
    end;
    
    function DwordXor(Buffer: T2DWords; Size: Word; Decrypt: Boolean): T2DWords;
    var
     K: Integer;
    begin  // if LeftSize = 2 then .. else  xor Bytes
     if ((Size shr 2) = 2) then  // <--- Always returns 2
      if (Decrypt = False) then
       for K := 0 to 1 do
        Result[K] := Buffer[K] xor BL3Key[K mod 2]
      else
       begin
        for K := 0 to 1 do
         Result[K] := Buffer[K]; // Fuck this < - > Result := Buffer;
       end;
    
     for K := 0 to 1 do
      Result[K] := SwapDword(Result[K]);
    end;
    
    procedure EncryptBlock (lpDest: Pointer; lpSource: Pointer; lpSize: Integer; Decrypt: Boolean);
    var
     Dwords: T2DWords;
    begin
     Dwords[0] := PDWord(Integer(lpSource))^;
     Dwords[1] := PDWord(Integer(lpSource) +4)^;
    
     if Decrypt then
      Dwords := Dec2DWords(GenerateKeys(Enc2DWords(DwordXor(Dwords, lpSize, Decrypt)), DecWZkeys8))
     else
      Dwords := Dec2DWords(GenerateKeys(Enc2DWords(DwordXor(Dwords, lpSize, Decrypt)), EncWZkeys8));
    
    
     if Decrypt then
      begin
       PDWord(Integer(lpDest))^    := (SwapDword(Dwords[0]) xor BL3Key[0]);
       PDWord(Integer(lpDest) +4)^ := (SwapDword(Dwords[1]) xor BL3Key[1]);
      end
     else
      begin
       PDWord(Integer(lpDest))^     := (SwapDword(Dwords[0])); //Swap
       PDWord(Integer(lpDest) +4)^  := (SwapDword(Dwords[1])); //Swap
      end;
    end;
    
    
    function EncDecC3C4_Plus(lpDest: Pointer; lpSource: Pointer; lpSize: Integer; Decrypt: Boolean): Integer;
    var
     lpTempDest, lpTempSrc: PByte;
     iOffset, Garbage: Integer;
    begin
     if lpDest = nil then
      begin
       Result := lpSize;
       Exit;
      end;
    
     lpTempDest := PByte(lpDest);
     lpTempSrc  := PByte(lpSource);
    
    
     iOffset := 0;
     if lpSize > 0 then
      begin
       while iOffset < lpSize  do
        begin
          EncryptBlock(lpTempDest + iOffset, lpTempSrc + iOffset, 8, Decrypt);
         Inc(iOffset, 8);
        end;
    
       if not Decrypt then
        PByte(Integer(lpDest) + iOffset)^ := iOffset - (lpSize);
    
       Inc(iOffset);
      end;
    
     if Decrypt then
      Result := (lpSize - lpTempSrc[lpSize -1])
     else
      begin
       Result := iOffset;
      end;
    end;
    
    function GetHdrSize(lpSource: Pointer): Byte;
    begin
     case PByte(lpSource)^ of
      $C1, $C3: Result := 2;
      $C2, $C4: Result := 3;
     else
      Result := 0;
     end;
    end;
    
    function GetHdr(lpSource: Pointer): Byte;
    begin
     Result := PByte(lpSource)^
    end;
    
    function GetPacketSize (lpSource: Pointer): Word;
    var
     Hdr: Byte;
    begin
     Hdr := GetHdr(lpSource);
     case Hdr of
      $C1, $C3: Result :=  PByte(Integer(lpSource) + 1)^;
      $C2, $C4: Result := (PByte(Integer(lpSource) + 1)^ shl 8) + PByte(Integer(lpSource) + 2)^;
     else
      Result := 0;
     end;
    end;
    
    function GetContentSize (lpSource: Pointer): Word;
    begin
     Result := GetPacketSize(lpSource) - GetHdrSize(lpSource)
    end;
    
    function EncryptDecrypt_C3C4(lpDest: Pointer; lpSource: Pointer): Integer;
    var
     HdrSize: Byte;
     ContentSize: Word;
     DecSize: Word;
    begin
     HdrSize := GetHdrSize(lpSource);
     ContentSize := GetContentSize(lpSource);
    
     DecSize := EncDecC3C4_Plus(Pointer(Integer(lpDest) + HdrSize), Pointer(Integer(lpSource) + HdrSize), ContentSize, True);
    
     Inc(DecSize, HdrSize -1);
     case PByte(lpSource)^ of
     $C3:
      begin
       PByte(Integer(lpDest))^ := PByte(lpSource)^;
       PByte(Integer(lpDest) +1)^ := DecSize;
      end;
     $C4:
      begin
       PByte(Integer(lpDest))^ := PByte(lpSource)^;
       PByte(Integer(lpDest) +1)^ := HiByte(DecSize);
       PByte(Integer(lpDest) +2)^ := LoByte(DecSize);
      end;
     end;
     Result := DecSize;
    end;
    
    function Encrypt_C3C4(lpDest: Pointer; lpSource: Pointer; Counter: Byte): Integer;
    var
     HdrSize: Byte;
     ContentSize: Word;
     EncSize: Word;
    begin
     HdrSize := GetHdrSize(lpSource);
     ContentSize := GetContentSize(lpSource);
    
     PByte(Integer(lpSource) +HdrSize)^ := Counter;
     EncSize := EncDecC3C4_Plus(Pointer(Integer(lpDest) + HdrSize), Pointer(Integer(lpSource) + HdrSize), ContentSize, False);
    
     Inc(EncSize, HdrSize);  //-1
     case PByte(lpSource)^ of
     $C3:
      begin
       PByte(Integer(lpDest))^ := PByte(lpSource)^;
       PByte(Integer(lpDest) +1)^ := EncSize;
      end;
     $C4:
      begin
       PByte(Integer(lpDest))^ := PByte(lpSource)^;
       PByte(Integer(lpDest) +1)^ := HiByte(EncSize);
       PByte(Integer(lpDest) +2)^ := LoByte(EncSize);
    
      end;
     end;
     Result := EncSize;
    end;
    
    procedure Decode32(lpDest: Pointer; lpLen, lpOffSet: Integer);
    var
     P: Integer;
    begin
     P := lpLen - 1;
     While (P > 0) do
      begin
       PByte(Integer(lpDest) +P)^ := PByte(Integer(lpDest) +P)^ xor PByte(Integer(lpDest) +(P -1))^ xor KeyByteC1C2[(P + lpOffSet) mod 32];
       Dec(P);
      end;
    end;
    
    procedure Encode32(lpDest: Pointer; lpLen, lpOffSet: Integer);
    var
     P: Integer;
    begin
     for P := 1 to lpLen do
      PByte(Integer(lpDest) +P)^ := PByte(Integer(lpDest) +P)^ xor PByte(Integer(lpDest) +(P -1))^ xor KeyByteC1C2[(P + lpOffSet) mod 32];
    end;
    
    procedure MU_Decode32(lpDest: Pointer);
    var
     HdrSize: Byte;
     ContentSize: Word;
    begin
     HdrSize := GetHdrSize(lpDest);
     ContentSize := GetContentSize(lpDest);
     Decode32(Pointer(Integer(lpDest) + (HdrSize +1)) , ContentSize, HdrSize);
    end;
    
    procedure MU_Encode32(lpSource: Pointer);
    var
     HdrSize: Byte;
     ContentSize: Word;
    begin
     HdrSize := GetHdrSize(lpSource);         //Dec C3 0C 01 0E 00 35 0C 6E 86 00 00 00
     ContentSize := GetContentSize(lpSource); //Enc C3 0C 01 0E F0 DD F2 59 7C B6 85 44
     Encode32(Pointer(Integer(lpSource) + (HdrSize +1)) , ContentSize, HdrSize);
    end;
    
    function DecryptC3C4(lpDest: Pointer; lpSource: Pointer; ToServer: Boolean): Integer;
    begin
     Result := EncryptDecrypt_C3C4(lpDest, lpSource);
    
     if ToServer then
      begin
    //   if (PByte(lpDest)^ = $C3) and (PByte(Integer(lpDest) +3)^ = $F1) then
    //    DecryptLevel2(lpDest);
    
       MU_Decode32(lpDest);
      end;
    end;
    
    function EncryptC3C4(lpDest: Pointer; lpSource: Pointer; Counter: Byte; ToServer: Boolean): Integer;
    begin
     if ToServer then
      begin
       MU_Encode32(lpSource);
    
    //   if (PByte(lpSource)^ = $C3) and (PByte(Integer(lpSource) +3)^ = $F1) then
    //    EncryptLevel2(lpSource);
      end;
    
     Result := Encrypt_C3C4(lpDest, lpSource, Counter);
    end;
    
    
    end.
    Code is hardly messed up, but i give a shit about it..
    Here is my work from Ex700 client, again 1/10 of all

    Code:
    unit uWzEncDec;
    
    interface
    
    uses
     Windows, System.SysUtils;
    
    const
     Keys: array [0 .. 43] of DWORD =  ($E2CB2C47, $676CCC60, $59C06192, $8AB3B66D,
       $23A82990, $4DA877B9, $254A0788, $83EFE892, $F0D21807, $527CED5D, $9A165576,
       $B51ED51A, $65298BF3, $5EACAF1A, $004F0813, $B30F3FF9, $7751A486, $83A69183,
       $94B9397C, $0D3F9C51, $3A3395F4, $EBF511C5, $954C2EB4, $082E330B, $94F0A80A,
       $C661B594, $E9744643, $2EB9425B, $630A3121, $0F8758D8, $5424534C, $CB251A98,
       $D422BA68, $4A4487F9, $6D124452, $5A7E6FAF, $9ADB16B7, $FF1583DA, $8B232CEC,
       $1FC6BC3C, $01FC75E5, $39036FF6, $DC4B0869, $C7808981);
    
      KeyByteC1C2: 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);
    
      LoginKeys: array [0..2] of Byte = ($FC, $CF, $AB);
    
     function DecryptC3C4(lpDest: Pointer; lpSource: Pointer; ToServer: Boolean): Integer;
     function EncryptC3C4(lpDest: Pointer; lpSource: Pointer; Counter: Byte; ToServer: Boolean): Integer;
     function EncodeIP(InVal: string): string;
     function EncodePort(Port: integer; IpLen: String):integer;
    
     procedure EncryptLevel2(lpSource: Pointer);
     procedure DecryptLevel2(lpSource: Pointer);
    
     procedure EncDecLogin(Data: PByteArray; Size: Integer);
     procedure DecodeC1(Data: PByteArray; HeaderSize, Length: Integer);
     procedure EncodeC1(Data: PByteArray; HeaderSize, Length: Integer);
     procedure _DecodeC1(DecryptResult, Data: PByteArray; HeaderSize, Length: Integer);
     procedure _EncodeC1(EncryptResult, Data: PByteArray; HeaderSize, Length: Integer);
    
    
    
    implementation
    
    function ROL(const value, shift: DWORD): DWORD;
    asm
     MOV ECX, EDX
     ROL EAX, CL
    end;
    
    function ROR(const value, shift: DWORD): DWORD;
    asm
     MOV ECX, EDX
     ROR EAX, CL
    end;
    
    function SAR(const Value, Shift: Byte): Byte; //EAX, ECX, EDX
    begin
     Result := Value shr Shift;
    end;
    
    procedure _DecodeC1(DecryptResult, Data: PByteArray; HeaderSize, Length: Integer);
    var
      K: Integer;
    begin
      for K := 0 to (Length - 1) do
        if (K <= 2) then
          DecryptResult[K] := Data[K + HeaderSize]
        else
          DecryptResult[K] := Data[K + HeaderSize] xor (Data[K - 1 + HeaderSize] xor KeyByteC1C2[K mod 32]);
    end;
    
    procedure _EncodeC1(EncryptResult, Data: PByteArray; HeaderSize, Length: Integer);
    var
      K: Integer;
    begin
      for K := 0 to (Length - 1) do
        if (K <= 2) then
          EncryptResult[K] := Data[K + HeaderSize]
        else
          EncryptResult[K] := Data[K + HeaderSize] xor (EncryptResult[K - 1 + HeaderSize] xor KeyByteC1C2[K mod 32]);
    end;
    
    
    procedure DecodeC1(Data: PByteArray; HeaderSize, Length: Integer);
    var
      I: Integer;
    begin
      for I := 0 to (Length - 1) do
        if (I <= 2) then
          Data[I] := Data[I + HeaderSize]
        else
          Data[I] := Data[I + HeaderSize] xor (Data[I - 1 + HeaderSize] xor KeyByteC1C2[I mod 32]);
    end;
    
    procedure EncodeC1(Data: PByteArray; HeaderSize, Length: Integer);
    var
      I: Integer;
    begin
      for I := 0 to (Length - 1) do
        if (I <= 2) then
          Data[I] := Data[I + HeaderSize]
        else
          Data[I] := Data[I + HeaderSize] xor (Data[I - 1 + HeaderSize] xor KeyByteC1C2[I mod 32]);
    end;
    
    procedure DecryptBlock(lpDest: Pointer; lpSource: Pointer);
    var
     dwDecBuffer: array [0 .. 3] of DWORD;
     TmpBuffer0, TmpBuffer3: DWORD;
     iOffset: LPDWORD;
     K: Integer;
     CL: Byte;
    begin
     FillMemory(lpDest, 16, 0);
     FillMemory(@dwDecBuffer, SizeOf(dwDecBuffer), 0);
     iOffset := @Keys[42];
    
     dwDecBuffer[0] := PDWord(Integer(lpSource))^  - PDWord(Integer(iOffset))^;
     dwDecBuffer[1] := PDWord(Integer(lpSource) + 4)^;
     dwDecBuffer[2] := PDWord(Integer(lpSource) + 8)^ - PDWord(Integer(iOffset) +4)^;
     dwDecBuffer[3] := PDWord(Integer(lpSource) + 12)^;
    
     Dec(iOffset, 2);
    
     for K := $14 downto 1 do
      begin
       TmpBuffer0 := dwDecBuffer[0];
       dwDecBuffer[0] := dwDecBuffer[3] - PDWord(Integer(iOffset))^;
       dwDecBuffer[3] := dwDecBuffer[2];
       dwDecBuffer[2] := dwDecBuffer[1] - PDWord(Integer(iOffset) +4)^;
    
       Dec(iOffset, 2);
    
       dwDecBuffer[1] := (TmpBuffer0 + TmpBuffer0 +1) * TmpBuffer0;
       TmpBuffer3 := (dwDecBuffer[3] + dwDecBuffer[3] +1) * dwDecBuffer[3];
    
       TmpBuffer3 := ROL(TmpBuffer3, 5);
       dwDecBuffer[1] := ROL(dwDecBuffer[1], 5);
    
       CL    := PByte(LongWord(Pointer(@dwDecBuffer[1]))+0)^;
       dwDecBuffer[2] := ROR(dwDecBuffer[2], CL);
    
       CL    := PByte(LongWord(Pointer(@TmpBuffer3))+0)^;
       dwDecBuffer[0] := ROR(dwDecBuffer[0], CL);
    
       dwDecBuffer[2] := dwDecBuffer[2] xor TmpBuffer3;
       dwDecBuffer[0] := dwDecBuffer[0] xor dwDecBuffer[1];
    
       dwDecBuffer[1] := TmpBuffer0;
      end;
     dwDecBuffer[3] := dwDecBuffer[3] - PDWord(Integer(iOffset) +4)^;
     dwDecBuffer[1] := dwDecBuffer[1] - PDWord(Integer(iOffset))^;
    
     PDWord(Integer(lpDest))^     := dwDecBuffer[0];
     PDWord(Integer(lpDest) +4)^  := dwDecBuffer[1];
     PDWord(Integer(lpDest) +8)^  := dwDecBuffer[2];
     PDWord(Integer(lpDest) +12)^ := dwDecBuffer[3];
    end;
    
    procedure EncryptBlock(lpDest: Pointer; lpSource: Pointer);
    var
     dwDecBuffer: array [0 .. 3] of DWORD;
     TmpBuffer1, TmpBuffer2, TmpBuffer3, _Enc1: DWORD;
     iOffset: Byte;
     K: Integer;
     CL: Byte;
    begin
     FillMemory(lpDest, 16, 0);
     FillMemory(@dwDecBuffer, SizeOf(dwDecBuffer), 0);
     iOffset := 0;
    
     TmpBuffer2     := PDWord(Integer(lpSource))^;
     dwDecBuffer[1] := PDword(@Keys[iOffset])^ + PDWord(Integer(lpSource) + 4)^;
     dwDecBuffer[2] := PDWord(Integer(lpSource) + 8)^;
     dwDecBuffer[3] := PDword(@Keys[iOffset +1])^ + PDWord(Integer(lpSource) + 12)^;
    
     Inc(iOffset, 2);
     _Enc1 := dwDecBuffer[2];
    
     for K := $14 downto 1 do
      begin
       TmpBuffer1 := (dwDecBuffer[1] + dwDecBuffer[1] +1) * dwDecBuffer[1];
       TmpBuffer3 := (dwDecBuffer[3] + dwDecBuffer[3] +1) * dwDecBuffer[3];
    
       TmpBuffer1 := ROL(TmpBuffer1, 5);
       TmpBuffer3 := ROL(TmpBuffer3, 5);
    
       dwDecBuffer[2] := TmpBuffer1 xor TmpBuffer2;
    
       CL    := PByte(LongWord(Pointer(@TmpBuffer3))+0)^;
       dwDecBuffer[2] := ROL(dwDecBuffer[2], CL);
    
       TmpBuffer3 := TmpBuffer3 xor _Enc1;
    
       CL    := PByte(LongWord(Pointer(@TmpBuffer1))+0)^;
       TmpBuffer3 := ROL(TmpBuffer3, CL);
    
       _Enc1 := dwDecBuffer[3];
       dwDecBuffer[3] := Keys[iOffset];
    
       TmpBuffer3 := TmpBuffer3 + PDword(@Keys[iOffset +1])^;
       TmpBuffer2 := dwDecBuffer[1];
    
       dwDecBuffer[3] := dwDecBuffer[3] + dwDecBuffer[2];
       dwDecBuffer[1] := TmpBuffer3;
       Inc(iOffset, 2);
      end;
     dwDecBuffer[2] := _Enc1 + PDword(@Keys[iOffset +1])^;
     dwDecBuffer[0] :=  PDword(@Keys[iOffset])^ + TmpBuffer2;
    
     PDWord(Integer(lpDest))^     := dwDecBuffer[0];
     PDWord(Integer(lpDest) +4)^  := dwDecBuffer[1];
     PDWord(Integer(lpDest) +8)^  := dwDecBuffer[2];
     PDWord(Integer(lpDest) +12)^ := dwDecBuffer[3];
    end;
    
    function Decrypt(lpDest: Pointer; lpSource: Pointer; lpSize: Integer): Integer;
    var
     lpTempDest, lpTempSrc: PByte;
     iOffset: Integer;
     Garbage: Word;
    begin
    if lpDest = nil then
      begin
       Result := lpSize;
       Exit;
      end;
    
     lpTempDest := PByte(lpDest);
     lpTempSrc  := PByte(lpSource);
    
     Garbage := lpTempSrc[lpSize -1];
    
     if lpSize > 0 then
      begin
       iOffset := 0;
       while iOffset < lpSize  do
        begin
         DecryptBlock(lpTempDest + iOffset, lpTempSrc + iOffset);
         Inc(iOffset, 16);
        end;
      end;
     Result := lpSize - Garbage;
    end;
    
    function Encrypt(lpDest: Pointer; lpSource: Pointer; lpSize: Integer): Integer;
    var
     lpTempDest, lpTempSrc: PByte;
     iOffset: Integer;
    begin
     if lpDest = nil then
      begin
       Result := lpSize;
       Exit;
      end;
    
     lpTempDest := PByte(lpDest);
     lpTempSrc  := PByte(lpSource); // False: $01 $0E $F0 $DD $F2 $59 $7C $B6 $85 $44 $88 $00 $00 $00 $00 $00 $CA $C4 $74 $C5  ir
                                    // True:  $01 $0E $F0 $DD $F2 $59 $7C $B6 $85 $44 $88 $EE $00 $00 $00 $00 $CA $C4 $74 $C5
     iOffset := 0;
     if lpSize > 0 then
      begin                       //$47 $DB $8A $C8 $41 $7A $BA $44 $B0 $78 $51 $04 $79 $D8 $14 $2D $00 vajadzigs
       while iOffset < lpSize  do //$36 $18 $A6 $57 $41 $89 $60 $DB $F7 $EB $F2 $89 $8A $7E $7D $C4 $00 ir
        begin
         EncryptBlock(lpTempDest + iOffset, lpTempSrc + iOffset);
         Inc(iOffset, 16);
        end;
       PByte(Integer(lpDest) + iOffset)^ := iOffset - (lpSize);
       Inc(iOffset);
      end;
     Result := iOffset +1; // Garbage
    end;
    
    function GetHdrSize(lpSource: Pointer): Byte;
    begin
     case PByte(lpSource)^ of
      $C1, $C3: Result := 2;
      $C2, $C4: Result := 3;
     else
      Result := 0;
     end;
    end;
    
    function GetHdr(lpSource: Pointer): Byte;
    begin
     Result := PByte(lpSource)^
    end;
    
    function GetPacketSize (lpSource: Pointer): Word;
    var
     Hdr: Byte;
    begin
     Hdr := GetHdr(lpSource);
     case Hdr of
      $C1, $C3: Result :=  PByte(Integer(lpSource) + 1)^;
      $C2, $C4: Result := (PByte(Integer(lpSource) + 1)^ shl 8) + PByte(Integer(lpSource) + 2)^;
     else
      Result := 0;
     end;
    end;
    
    function GetContentSize (lpSource: Pointer): Word;
    begin
     Result := GetPacketSize(lpSource) - GetHdrSize(lpSource)
    end;
    
    function Decrypt_C3C4(lpDest: Pointer; lpSource: Pointer): Integer;
    var
     HdrSize: Byte;
     ContentSize: Word;
     DecSize: Word;
    begin
     HdrSize := GetHdrSize(lpSource);
     ContentSize := GetContentSize(lpSource);
    
     DecSize := Decrypt(Pointer(Integer(lpDest) + HdrSize), Pointer(Integer(lpSource) + HdrSize), ContentSize);
    
     Inc(DecSize, HdrSize -1);
     case PByte(lpSource)^ of
     $C3:
      begin
       PByte(Integer(lpDest))^ := PByte(lpSource)^;
       PByte(Integer(lpDest) +1)^ := DecSize;
      end;
     $C4:
      begin
       PByte(Integer(lpDest))^ := PByte(lpSource)^;
       PByte(Integer(lpDest) +1)^ := HiByte(DecSize);
       PByte(Integer(lpDest) +2)^ := LoByte(DecSize);
      end;
     end;
     Result := DecSize;
    end;
    
    function Encrypt_C3C4(lpDest: Pointer; lpSource: Pointer; Counter: Byte): Integer;
    var
     HdrSize: Byte;
     ContentSize: Word;
     EncSize: Word;
    begin
     HdrSize := GetHdrSize(lpSource);
     ContentSize := GetContentSize(lpSource);
    
     PByte(Integer(lpSource) +HdrSize)^ := Counter;
     EncSize := Encrypt(Pointer(Integer(lpDest) + HdrSize), Pointer(Integer(lpSource) + HdrSize), ContentSize);
    
     Inc(EncSize, HdrSize -1);
     case PByte(lpSource)^ of
     $C3:
      begin
       PByte(Integer(lpDest))^ := PByte(lpSource)^;
       PByte(Integer(lpDest) +1)^ := EncSize;
      end;
     $C4:
      begin
       PByte(Integer(lpDest))^ := PByte(lpSource)^;
       PByte(Integer(lpDest) +1)^ := HiByte(EncSize);
       PByte(Integer(lpDest) +2)^ := LoByte(EncSize);
    
      end;
     end;
     Result := EncSize
    end;
    
    procedure Decode32(lpDest: Pointer; lpLen, lpOffSet: Integer);
    var
     P: Integer;
    begin
     P := lpLen - 1;
     While (P > 0) do
      begin
       PByte(Integer(lpDest) +P)^ := PByte(Integer(lpDest) +P)^ xor PByte(Integer(lpDest) +(P -1))^ xor KeyByteC1C2[(P + lpOffSet) mod 32];
       Dec(P);
      end;
    end;
    
    procedure Encode32(lpDest: Pointer; lpLen, lpOffSet: Integer);
    var
     P: Integer;
    begin
     for P := 1 to lpLen do
      PByte(Integer(lpDest) +P)^ := PByte(Integer(lpDest) +P)^ xor PByte(Integer(lpDest) +(P -1))^ xor KeyByteC1C2[(P + lpOffSet) mod 32];
    end;
    
    procedure MU_Decode32(lpDest: Pointer);
    var
     HdrSize: Byte;
     ContentSize: Word;
    begin
     HdrSize := GetHdrSize(lpDest);
     ContentSize := GetContentSize(lpDest);
     Decode32(Pointer(Integer(lpDest) + (HdrSize +1)) , ContentSize, HdrSize);
    end;
    
    procedure MU_Encode32(lpSource: Pointer);
    var
     HdrSize: Byte;
     ContentSize: Word;
    begin
     HdrSize := GetHdrSize(lpSource);         //Dec C3 0C 01 0E 00 35 0C 6E 86 00 00 00
     ContentSize := GetContentSize(lpSource); //Enc C3 0C 01 0E F0 DD F2 59 7C B6 85 44
     Encode32(Pointer(Integer(lpSource) + (HdrSize +1)) , ContentSize, HdrSize);
    end;
    
    function DecryptC3C4(lpDest: Pointer; lpSource: Pointer; ToServer: Boolean): Integer;
    begin
     Result := Decrypt_C3C4(lpDest, lpSource);
    
     if ToServer then
      begin
    //   if (PByte(lpDest)^ = $C3) and (PByte(Integer(lpDest) +3)^ = $F1) then
    //    DecryptLevel2(lpDest);
    
       MU_Decode32(lpDest);
      end;
    end;
    
    function EncryptC3C4(lpDest: Pointer; lpSource: Pointer; Counter: Byte; ToServer: Boolean): Integer;
    begin
     if ToServer then
      begin
       MU_Encode32(lpSource);
    
    //   if (PByte(lpSource)^ = $C3) and (PByte(Integer(lpSource) +3)^ = $F1) then
    //    EncryptLevel2(lpSource);
      end;
    
     Result := Encrypt_C3C4(lpDest, lpSource, Counter);
    end;
    
    procedure DecryptLevel2(lpSource: Pointer);
    var
     Offset: Byte;
     ContentSize: Word;
     PBuffer: PByte;
     Condition, Condition2: Byte;
    begin
     Offset := GetHdrSize(lpSource) +2; // Counter = 2
     ContentSize := GetContentSize(lpSource);
     PBuffer := PByte(lpSource) + Offset;
    
     if not (ContentSize >= 4) then
      Exit // No Decryption for this size
     else
     if not (ContentSize >= 8) then
      begin
       PByte(PBuffer +3)^ := PByte(PBuffer +3)^ xor $85; //09CB6897
    
       Condition   := SAR(PByte(PBuffer +3)^, 4) and 1;
       Condition2  := SAR(PByte(PBuffer +3)^, 2) and 1;
    
       if (Condition = 0) then
        PByte(PBuffer +3)^ := PByte(PBuffer +3)^ and $EF //09BFCD94
       else
        PByte(PBuffer +3)^ := PByte(PBuffer +3)^ or $10; //09CB6573
    
       if (Condition2 = 0) then
        PByte(PBuffer +3)^ := PByte(PBuffer +3)^ and $EF //09BFCD94
       else
        PByte(PBuffer +3)^ := PByte(PBuffer +3)^ or $10; //09CB6573
    
       Condition   := SAR(PByte(PBuffer +7)^, 4) and 1;
       Condition2  := SAR(PByte(PBuffer +7)^, 5) and 1;
    
       if (Condition = 0) then
        PByte(PBuffer +7)^ := PByte(PBuffer +7)^ and $DF //09BFCCF4
       else
        PByte(PBuffer +7)^ := PByte(PBuffer +7)^ or $20; //09CB6356
    
    
       if (Condition2 = 0) then
        PByte(PBuffer +7)^ := PByte(PBuffer +7)^ and $EF //09BFCD36
       else
        PByte(PBuffer +7)^ := PByte(PBuffer +7)^ or $10;
      end
     else
     if not (ContentSize >= 16) then
      begin
       PByte(PBuffer +3)^ := PByte(PBuffer +3)^ xor $85; //09CB6897
    
       Condition   := SAR(PByte(PBuffer +3)^, 4) and 1;
       Condition2  := SAR(PByte(PBuffer +3)^, 2) and 1;
    
       if (Condition = 0) then
        PByte(PBuffer +3)^ := PByte(PBuffer +3)^ and $EF //09BFCD94
       else
        PByte(PBuffer +3)^ := PByte(PBuffer +3)^ or $10; //09CB6573
    
       if (Condition2 = 0) then
        PByte(PBuffer +3)^ := PByte(PBuffer +3)^ and $EF //09BFCD94
       else
        PByte(PBuffer +3)^ := PByte(PBuffer +3)^ or $10; //09CB6573
    
       Condition   := SAR(PByte(PBuffer +7)^, 4) and 1;
       Condition2  := SAR(PByte(PBuffer +7)^, 5) and 1;
    
       if (Condition = 0) then
        PByte(PBuffer +7)^ := PByte(PBuffer +7)^ and $DF //09BFCCF4
       else
        PByte(PBuffer +7)^ := PByte(PBuffer +7)^ or $20; //09CB6356
    
    
       if (Condition2 = 0) then
        PByte(PBuffer +7)^ := PByte(PBuffer +7)^ and $EF //09BFCD36
       else
        PByte(PBuffer +7)^ := PByte(PBuffer +7)^ or $10;
      end
     else
     if not (ContentSize >= 32) then
      begin
       PByte(PBuffer +$1F)^ := PByte(PBuffer +$1F)^ xor $7D;
    
       Condition := PByte(PBuffer +$10)^;
       PByte(PBuffer +$10)^ := PByte(PBuffer +$18)^;
       PByte(PBuffer +$18)^ := Condition;
    
    
       Condition2 := (PByte(PBuffer +$1A)^ shr 5);
       PByte(PBuffer)^ := PByte(PBuffer +$1A)^ or Condition2;
       PByte(PBuffer +$1A)^ := (PByte(PBuffer)^ shl 3);
    
       Condition := PByte(PBuffer +3)^;
       PByte(PBuffer +3)^ := PByte(PBuffer +$18)^;
       PByte(PBuffer +$18)^ := Condition;
    
       Condition := (PByte(PBuffer +4)^ shl 2);
       PByte(PBuffer +4)^ := PByte(PBuffer +4)^ shr 6;
       PByte(PBuffer +4)^ := (PByte(PBuffer +4)^ or Condition);
    
    
       Condition  := (PByte(PBuffer +2)^ shr 5) and 1;
       Condition2 := (PByte(PBuffer +2)^ shr 2) and 1;
    
       if (Condition2 = 0) then
        PByte(PBuffer +2)^ := PByte(PBuffer +2)^ and $DF //09CB75DE
       else
        PByte(PBuffer +2)^ := PByte(PBuffer +2)^ or $20; //09CB75D0
    
       if (Condition = 0) then
        PByte(PBuffer +2)^ := PByte(PBuffer +2)^ and $FB //09BFD34A
       else
        PByte(PBuffer +2)^ := PByte(PBuffer +2)^ or 4;   //09CB75B7
    
       Condition  := (PByte(PBuffer +6)^ shr 7) and 1; //8bit
       Condition2 := (PByte(PBuffer +6)^ shr 6) and 1; //7bit
    
       if (Condition = 0) then
        PByte(PBuffer +6)^ := PByte(PBuffer +6)^ and $BF //09CB74CB
       else
        PByte(PBuffer +6)^ := PByte(PBuffer +6)^ or $40; //09CB74BD
    
       if (Condition2 = 0) then
        PByte(PBuffer +6)^ := PByte(PBuffer +6)^ and $7F //09CB755F
       else
        PByte(PBuffer +6)^ := PByte(PBuffer +6)^ or $80; //$FFFFFF7F
    
       PByte(PBuffer +$11)^ := PByte(PBuffer +$11)^ xor $AC;
    
       Condition  := (PByte(PBuffer +$15)^ shr 2) and 1;
       Condition2 := (PByte(PBuffer +$15)^ shr 2) and 1;
    
       if (Condition = 0) then
        PByte(PBuffer +$15)^ := PByte(PBuffer +$15)^ and $FB //9CB740B
       else
        PByte(PBuffer +$15)^ := PByte(PBuffer +$15)^ or 4;
    
       if (Condition2 = 0) then
        PByte(PBuffer +$15)^ := PByte(PBuffer +$15)^ and $DF
       else
        PByte(PBuffer +$15)^ := PByte(PBuffer +$15)^ or 4;
    
       PByte(PBuffer +1)^ := PByte(PBuffer +1)^ xor $1A;  //09CB7290
      end
     else
      begin
       Condition  := PByte(PBuffer +$C)^ shl 6;
       Condition2 := PByte(PBuffer +$C)^ shr 2;
       PByte(PBuffer +$C)^ := (Condition or Condition2);
    
       Condition  := PByte(PBuffer +$A)^ shr 1 and 1;
       Condition2 := PByte(PBuffer +$A)^ shr 1 and 1;
    
       if (Condition = 0) then
        PByte(PBuffer +$A)^ := PByte(PBuffer +$A)^ and $FD //09BFD1E6
       else
        PByte(PBuffer +$A)^ := PByte(PBuffer +$A)^ or $20;
    
       if (Condition2 = 0) then
        PByte(PBuffer +$A)^ := PByte(PBuffer +$A)^ and $FD //09BFD251
       else
        PByte(PBuffer +$A)^ := PByte(PBuffer +$A)^ or 2;   //09BFD242
    
       PByte(PBuffer +8)^ := PByte(PBuffer +8)^ xor $DF;
       PByte(PBuffer)^ := PByte(PBuffer)^ xor $A;
    
       Condition := PByte(PBuffer +$B)^;
       PByte(PBuffer +$B)^ := PByte(PBuffer +2)^;
       PByte(PBuffer +$B)^ := Condition;
      end;
    end;
    
    procedure EncryptLevel2(lpSource: Pointer);  //1.14.17
    var
     Offset: Byte;
     ContentSize: Word;
     PBuffer: PByte;
     Condition, Condition2: Byte;
    begin
     Offset := GetHdrSize(lpSource) +2; // Counter = 2
     ContentSize := GetContentSize(lpSource);
     PBuffer := PByte(lpSource) + Offset;
    
     if not (ContentSize >= 4) then
      Exit // No Encryption for this size
     else
     if not (ContentSize >= 8) then
      begin
       PByte(PBuffer +2)^ := ((PByte(PBuffer +2)^ shr 2) or (PByte(PBuffer +2)^ shl 6)) xor $91;
       PByte(PBuffer +3)^ := PByte(PBuffer +3)^ xor $F6; //09CB62E6
      end
     else
     if not (ContentSize >= 16) then //006681FB
      begin
       Condition   := SAR(PByte(PBuffer +7)^, 4) and 1;
       Condition2  := SAR(PByte(PBuffer +7)^, 5) and 1;
    
       if (Condition = 0) then
        PByte(PBuffer +7)^ := PByte(PBuffer +7)^ and $DF //09BFCCF4
       else
        PByte(PBuffer +7)^ := PByte(PBuffer +7)^ or $20; //09CB6356
    
    
       if (Condition2 = 0) then
        PByte(PBuffer +7)^ := PByte(PBuffer +7)^ and $EF //09BFCD36
       else
        PByte(PBuffer +7)^ := PByte(PBuffer +7)^ or $10;
    
       Condition   := SAR(PByte(PBuffer +3)^, 4) and 1;
       Condition2  := SAR(PByte(PBuffer +3)^, 2) and 1;
    
       if (Condition = 0) then
        PByte(PBuffer +3)^ := PByte(PBuffer +3)^ and $EF //09BFCD94
       else
        PByte(PBuffer +3)^ := PByte(PBuffer +3)^ or $10; //09CB6573
    
       if (Condition2 = 0) then
        PByte(PBuffer +3)^ := PByte(PBuffer +3)^ and $EF //09BFCD94
       else
        PByte(PBuffer +3)^ := PByte(PBuffer +3)^ or $10; //09CB6573
    
       PByte(PBuffer +3)^ := PByte(PBuffer +3)^ xor $85; //09CB6897
      end
     else
     if not (ContentSize >= 32) then // Login packet
      begin
       PBuffer := PByte(lpSource) + Offset;
       PByte(PBuffer +1)^ := PByte(PBuffer +1)^ xor $1A;  //09CB7290
    
       Condition  := SAR(PByte(PBuffer +$15)^, 2) and 1;
       Condition2 := SAR(PByte(PBuffer +$15)^, 2) and 1;
    
       if (Condition = 0) then
        PByte(PBuffer +$15)^ := PByte(PBuffer +$15)^ and $FB //9CB740B
       else
        PByte(PBuffer +$15)^ := PByte(PBuffer +$15)^ or 4;
    
       if (Condition2 = 0) then
        PByte(PBuffer +$15)^ := PByte(PBuffer +$15)^ and $DF
       else
        PByte(PBuffer +$15)^ := PByte(PBuffer +$15)^ or 4;
    
        Condition  := SAR(PByte(PBuffer +6)^, 7) and 1;
        Condition2 := SAR(PByte(PBuffer +6)^, 6) and 1;
    
       if (Condition = 0) then
        PByte(PBuffer +6)^ := PByte(PBuffer +6)^ and $BF //09CB74CB
       else
        PByte(PBuffer +6)^ := PByte(PBuffer +6)^ or $40; //09CB74BD
    
       if (Condition2 = 0) then
        PByte(PBuffer +6)^ := PByte(PBuffer +6)^ and $7F //09CB755F
       else
        PByte(PBuffer +6)^ := PByte(PBuffer +6)^ or $80; //$FFFFFF7F
    
       PByte(PBuffer +$11)^ := PByte(PBuffer +$11)^ xor $AC;
    
       Condition  := SAR(PByte(PBuffer +2)^, 5) and 1;
       Condition2 := SAR(PByte(PBuffer +2)^, 2) and 1;
    
       if (Condition = 0) then
        PByte(PBuffer +2)^ := PByte(PBuffer +2)^ and $FB //09BFD34A
       else
        PByte(PBuffer +2)^ := PByte(PBuffer +2)^ or 4;   //09CB75B7
    
       if (Condition2 = 0) then
        PByte(PBuffer +2)^ := PByte(PBuffer +2)^ and $DF //09CB75DE
       else
        PByte(PBuffer +2)^ := PByte(PBuffer +2)^ or $20; //09CB75D0
    
    
       Condition := SAR(PByte(PBuffer +4)^, 2);
       PByte(PBuffer +4)^ := PByte(PBuffer +4)^ shl 6;
       PByte(PBuffer +4)^ := (PByte(PBuffer +4)^ or Condition);
    
       Condition := PByte(PBuffer +$18)^;
       PByte(PBuffer +$18)^ := PByte(PBuffer +3)^;
       PByte(PBuffer +3)^   := Condition;
    
       Condition  := SAR(PByte(PBuffer +$1A)^, 3); //09CB7680
       Condition2 := (PByte(PBuffer +$1A)^ shl 5);
       PByte(PBuffer)^ := (Condition or Condition2);
       PByte(PBuffer +$1A)^ := Condition;
    
       Condition := PByte(PBuffer +$10)^;
       PByte(PBuffer +$10)^ := PByte(PBuffer +$18)^;
       PByte(PBuffer +$18)^ := Condition;
    
       PByte(PBuffer +$1F)^ := PByte(PBuffer +$1F)^ xor $7D;
      end
     else
      begin
       Condition := PByte(PBuffer +2)^;
       PByte(PBuffer +2)^ := PByte(PBuffer +$B)^;
       PByte(PBuffer +$B)^ := Condition;
    
       PByte(PBuffer +8)^ := PByte(PBuffer +8)^ xor $DF;
       PByte(PBuffer)^ := PByte(PBuffer)^ xor $A;
    
       Condition  := SAR(PByte(PBuffer +$A)^, 1) and 1;
       Condition2 := SAR(PByte(PBuffer +$A)^, 5) and 1;
    
       if (Condition = 0) then
        PByte(PBuffer +$A)^ := PByte(PBuffer +$A)^ and $FD //09BFD1E6
       else
        PByte(PBuffer +$A)^ := PByte(PBuffer +$A)^ or $20;
    
       if (Condition2 = 0) then
        PByte(PBuffer +$A)^ := PByte(PBuffer +$A)^ and $FD //09BFD251
       else
        PByte(PBuffer +$A)^ := PByte(PBuffer +$A)^ or 2;   //09BFD242
    
       Condition  := SAR(PByte(PBuffer +$C)^, 6);
       Condition2 := PByte(PBuffer +$C)^ shl 2;
       PByte(PBuffer +$C)^ := (Condition or Condition2);
      end;
    end;
    
    function EncodeIP(InVal: string): string;
    var
      Position, I: Integer;
    begin
      Result := '';
      Position := 0;
      for I := 1 to Length(InVal) do
      begin
        Position := Position + 1;
        case Position of
          1: Result := Result + Chr(Ord(InVal[I]) + 12);
          2: Result := Result + Chr(Ord(InVal[I]) + 7);
          3: Result := Result + Chr(Ord(InVal[I]) + 3);
          4:
           begin
            Result := Result + Chr(Ord(InVal[I]) + 19);
            Position := 0;
           end;
        end;
      end;
    end;
    
    function EncodePort(Port: integer; IpLen: String):integer;
    var
     X: Integer;
     Tmp: Integer;
    begin
     Tmp := 0;
     X := Length(IpLen) mod 4;
      case X of
       0: Tmp := Port + 12 - Port div 4 mod 4 *8;
       1: Tmp := Port +  7 - Port mod 8 * 2;
       2: Tmp := Port +  3 - Port mod 4 * 2;
       3: Tmp := Port + 19 - Port mod 4 * 2 - Port div 16 mod 2 * 32;
      end;
     Result := Tmp;
    end;
    
    procedure EncDecLogin(Data: PByteArray; Size: Integer);
    var
     K: Integer;
    begin
     for K := 0 to (Size - 1) do
      Data[K] := Data[K] xor LoginKeys[K mod 3];
    end;
    
    
    end.


  2. #2
    Hybrid Gembrid is offline
    MemberRank
    Mar 2006 Join Date
    1,121Posts

    Re: Reversing Ex700, Ex700Plus protocol crypt

    be smarter, use cryptopp(main uses it), don't reverse algorithms, but find out what algorithm it uses (2nd or 3rd virtual function returns it's name :D), also in virtual functions you will find the SetKey function, so it will be easy to catch the key.

    same thing goes to hash algorithm (hash value determines what hash algorithm and what enc/dec algorithm will be used next).

    Swap and Xor thingy may be better remove for the time you are unwinding the c3 enc/dec.

    and as i see ex700 and ex700plus uses same c3 enc/dec, the initial hash value is different.


    it's cool to share knowledge, but i don't think enc/dec will serve in good purposes :D

  3. #3
    Apprentice jansonbuton is offline
    MemberRank
    Jun 2012 Join Date
    12Posts

    Re: Reversing Ex700, Ex700Plus protocol crypt

    I'm not sure how it was before version 1.04.19 (because the 2048 packet limit was quite high) but IMO now encryption changes like this:

    - they have 2 pools of functions and use 2 hash values: hash1 = <0, 9>, hash2 = <0, 7>
    - first pool of functions is made of 9 items, and they are for hash1 values = <0, 8>
    - then, if hash1 = 9, they use another pool of 8 functions, and hash2 = <0, 7> tells what function it is
    - encryption may change after 8th, 16h, 24th (...) packet c3
    - encryption change to hash1 = <0, 8> is always final: no more changes after
    - encryption change to hash1 = 9 is never final: another change is guaranteed to happen
    - initial settings are such, that hash1 = 9 and hash2 = 4, so the change after 8th packet is guaranteed,
    and it's like ~90% for it to be the only change (hash1 = <0,8>). If not, then after 16th packet is another change with ~90% to be the last, and so on
    - key(s) to compute hashes depend on data sent inside network packets: fixed data result in fixed crypt changes

    P.s. What I mean by "hash" is more like "hash & 7" - the final index to a table of function pointers
    P.p.s. I'm total beginner in reversing, and in the process of learning it xD so none of this may be true but I think, it is :)

  4. #4
    Member city7 is offline
    MemberRank
    May 2011 Join Date
    92Posts

    Re: Reversing Ex700, Ex700Plus protocol crypt

    There is no VC++?

  5. #5
    NN - Nord & Noob mauka is online now
    MemberRank
    Jul 2004 Join Date
    1,735Posts

    Re: Reversing Ex700, Ex700Plus protocol crypt

    use google to see data types of delphi and C++
    Convert not hard, but does it worth?
    xor is ^
    shl is <<
    shr is >>
    and is &
    or is |
    not is !

    Pbyte is same *Char or *Byte

    Code:
       Keys[0] := CKey[(TmpDword shr $18) and $3F];
       Keys[1] := CXor1[(TmpDword shr $10) and $3F];
       Keys[2] := CXor2[(TmpDword shr   8) and $3F];
       Keys[3] := CXor3[TmpDword and $3F];
    Code:
       Keys[0] := CKey[(TmpDword >> 0x18) & 0x3F];
       Keys[1] := CXor1[(TmpDword >> 0x10) & 0x3F];
       Keys[2] := CXor2[(TmpDword >>   0x08) & 0x3F];
       Keys[3] := CXor3[TmpDword & $3F];
    http://www.roblocher.com/whitepapers/opascal.aspx
    Last edited by mauka; 25-01-13 at 07:14 AM.

  6. #6
    Member city7 is offline
    MemberRank
    May 2011 Join Date
    92Posts

    Re: Reversing Ex700, Ex700Plus protocol crypt

    Written DLL?

  7. #7
    NN - Nord & Noob mauka is online now
    MemberRank
    Jul 2004 Join Date
    1,735Posts

    Re: Reversing Ex700, Ex700Plus protocol crypt

    Its only partial encdec, dont waste time on it! Use http://www.chilkatsoft.com/, wz uses it for protocol crypt!

  8. #8
    NN - Nord & Noob mauka is online now
    MemberRank
    Jul 2004 Join Date
    1,735Posts

    Re: Reversing Ex700, Ex700Plus protocol crypt

    Anyone here research it? :D

  9. #9
    Kingdom of Shadows [RCZ]ShadowKing is offline
    MemberRank
    Jul 2007 Join Date
    1,644Posts

    Re: Reversing Ex700, Ex700Plus protocol crypt

    I may start debugging the main to reproduce the use of cryptopp after I finish some projects for the university.

    EDIT: it looks like they're using the 3-way encryption from cryptopp
    Last edited by [RCZ]ShadowKing; 13-12-13 at 08:46 PM.

  10. #10
    NN - Nord & Noob mauka is online now
    MemberRank
    Jul 2004 Join Date
    1,735Posts

    Re: Reversing Ex700, Ex700Plus protocol crypt

    Last time i was checking.. WZ was useing more then 8 crypt algo from crypto++ I never find out, how wz switch algo from DES to another etc...

  11. #11
    Kingdom of Shadows [RCZ]ShadowKing is offline
    MemberRank
    Jul 2007 Join Date
    1,644Posts

    Re: Reversing Ex700, Ex700Plus protocol crypt

    I found in PC a main that is from mublue version, ex700+ compiled(by some chinese guy) from the leaked sources. It is not obfuscated and maybe you can track the code better.
    Link: Download muchs.rar from Sendspace.com - send big files the easy way
    (it had a dll hooked but couldn't find it so I just skipped it)



Advertisement