FFXIVLauncher-Netmaui

Форк
0
123 строки · 3.9 Кб
1
using System;
2
using System.Collections.Generic;
3
using System.Diagnostics;
4
using System.IO;
5
using System.Linq;
6
using System.Text;
7
using System.Threading.Tasks;
8
using Serilog;
9
using XIVLauncher.Common.Encryption.BlockCipher;
10
using XIVLauncher.Common.PlatformAbstractions;
11
using XIVLauncher.Common.Util;
12

13
namespace XIVLauncher.Common.Encryption;
14

15
public class Ticket
16
{
17
    public string Text { get; }
18
    public int Length { get; }
19

20
    private const string FUCKED_GARBAGE_ALPHABET = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-_";
21

22
    private Ticket(string text, int length)
23
    {
24
        this.Text = text;
25
        this.Length = length;
26
    }
27

28
    public static async Task<Ticket?> Get(ISteam steam)
29
    {
30
        var ticketBytes = await steam.GetAuthSessionTicketAsync().ConfigureAwait(true);
31

32
        if (ticketBytes == null)
33
            return null;
34

35
        return EncryptAuthSessionTicket(ticketBytes, steam.GetServerRealTime());
36
    }
37

38
    public static Ticket EncryptAuthSessionTicket(byte[] ticket, uint time)
39
    {
40
        time -= 5;
41
        time -= time % 60; // Time should be rounded to nearest minute.
42

43
        var ticketString = BitConverter.ToString(ticket).Replace("-", "").ToLower();
44
        var rawTicketBytes = Encoding.ASCII.GetBytes(ticketString);
45

46
        var rawTicket = new byte[rawTicketBytes.Length + 1];
47
        Array.Copy(rawTicketBytes, rawTicket, rawTicketBytes.Length);
48
        rawTicket[rawTicket.Length - 1] = 0;
49

50
        var blowfishKey = $"{time:x08}#un@e=x>";
51

52
        using var memorySteam = new MemoryStream();
53
        using var binaryWriter = new BinaryWriter(memorySteam);
54

55
        /* REGULAR SUM + TICKET */
56
        ushort ticketSum = 0;
57

58
        foreach (byte b in rawTicket)
59
        {
60
            ticketSum += b;
61
        }
62

63
        binaryWriter.Write(ticketSum);
64
        binaryWriter.Write(rawTicket);
65

66
        /* GARBAGE */
67
        int castTicketSum = unchecked((short)ticketSum);
68
        Log.Information($"{castTicketSum:X}");
69
        var seed = time ^ castTicketSum;
70
        var rand = new CrtRand((uint)seed);
71

72
        var numRandomBytes = ((ulong)(rawTicket.Length + 9) & 0xFFFFFFFFFFFFFFF8) - 2 - (ulong)rawTicket.Length;
73
        var garbage = new byte[numRandomBytes];
74

75
        uint fuckedSum = BitConverter.ToUInt32(memorySteam.ToArray(), 0);
76

77
        for (var i = 0u; i < numRandomBytes; i++)
78
        {
79
            var randChar = FUCKED_GARBAGE_ALPHABET[(int)(fuckedSum + rand.Next()) & 0x3F];
80
            garbage[i] = (byte)randChar;
81
            fuckedSum += randChar;
82
        }
83

84
        binaryWriter.Write(garbage);
85

86
        memorySteam.Seek(0, SeekOrigin.Begin);
87
        binaryWriter.Write(fuckedSum);
88

89
        Log.Information("[STEAM] time: {Time}, bfKey: {FishKey}, rawTicket.Length: {TicketLen}, ticketSum: {TicketSum}, fuckedSum: {FuckedSum}, seed: {Seed}, numRandomBytes: {NumRandomBytes}", time,
90
            blowfishKey, rawTicket.Length, ticketSum, fuckedSum, seed, numRandomBytes);
91

92
        /* ENC + SPLIT */
93
        var finalBytes = memorySteam.ToArray();
94

95
        var t = finalBytes[0];
96
        finalBytes[0] = finalBytes[1];
97
        finalBytes[1] = t;
98

99
        var keyBytes = Encoding.ASCII.GetBytes(blowfishKey);
100

101
        var blowfish = new Blowfish(keyBytes);
102
        var ecb = new Ecb<Blowfish>(blowfish);
103

104
        var encBytes = new byte[finalBytes.Length];
105
        Debug.Assert(encBytes.Length % 8 == 0);
106

107
        ecb.Encrypt(finalBytes, encBytes);
108
        var encString = GameHelpers.ToMangledSeBase64(encBytes);
109

110
        const int SPLIT_SIZE = 300;
111
        var parts = ChunksUpto(encString, SPLIT_SIZE).ToArray();
112

113
        var finalString = string.Join(",", parts);
114

115
        return new Ticket(finalString, finalString.Length - (parts.Length - 1));
116
    }
117

118
    private static IEnumerable<string> ChunksUpto(string str, int maxChunkSize)
119
    {
120
        for (var i = 0; i < str.Length; i += maxChunkSize)
121
            yield return str.Substring(i, Math.Min(maxChunkSize, str.Length - i));
122
    }
123
}

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.