Format du flux de spectateurs de League of Legends

12

Intro

J'ai bidouillé avec le système de spectateurs pour LoL dans l'espoir de finalement gratter les données des flux et de créer un ensemble de données avec pour analyse. Je comprends qu'il existe déjà des API et des techniques non officielles, mais je recherche des événements de jeu vraiment spécifiques (champion kills, turret kills, item puchases, jungle mob kills, champion coordonnés pour des événements particuliers, etc.).

Ce que j'ai compris jusqu'à présent

Lorsque vous commencez à observer un jeu (en NA), votre client se connecte à l'hôte suivant:

spectator.na.lol.riotgames.com:8088

Je suppose que cet hôte est soutenu par Amazon AWS ou similaire. Quoi qu'il en soit, la prochaine chose qui se passe est que le client envoie une demande de version au serveur spectate:

GET / mode observateur / repos / consommateur / version

Cela renvoie quelle que soit la version actuelle du serveur spectateur. Ex: '1.80.54'

Ensuite, le client envoie une demande pour les métadonnées du jeu:

GET / mode observateur / rest / consumer / getGameMetaData / NA1 / [gameid] / [some random nonce] / token

Cela renvoie des métadonnées sur le jeu. Un exemple de ces données: http://pastebin.com/3N4qs0hx

Le client connaît maintenant les paramètres selon lesquels la session de spectateur doit progresser. Il essaie de localiser le dernier bloc de données en appelant:

GET / mode observateur / repos / consommateur / getLastChunkInfo / NA1 / [gameid] / 30000 / token

Exemple de ces données: http://pastebin.com/Cj7dEAr9

Une fois les blocs de données identifiés, il leur est demandé:

GET / mode observateur / repos / consommateur / getGameDataChunk / NA1 / [gameid] / [token #] / token

Exemple de données d'un jeton (binaire converti en hexadécimal): http: // pastebin.com / GyqPRP5J

Le jeu alterne entre l'appel de getLastChunkInfo et getGameDataChunk à mesure que les données deviennent disponibles à partir du flux de relecture. Il existe également un appel qui se produit après avoir récupéré environ 5 morceaux:

GET / mode observateur / repos / consommateur / getKeyFrame / NA1 / [gameid] / [somechunkid] / token

Je crois que cet appel ne se produit qu'au démarrage de la relecture et chaque fois que l'utilisateur cherche à une heure différente.

Je sais que le jeu utilise le cryptage à un certain niveau. Je pense que c'est Blowfish ECB, avec la clé réelle spécifiée sur la ligne de commande. J'ai tenté de décrypter ces jetons à l'aide de la clé de la session, mais ils semblent toujours assez aléatoires.

Modifier 23/03/2013

  • J'ai déterminé que les jetons ne sont probablement pas chiffrés en modifiant l'argument de ligne de commande contenant la clé et en relançant le jeu à partir du débogueur (il a chargé la relecture correctement).
  • Les jetons semblent être compressés. Il y a un appel à un sous-programme qui, s'il retourne un entier non nul, déclenchera ce qui suit:

    if ( sub_B71120(v21, v15, (int *)&Size, *(_DWORD *)(v6 + 108)) )
    {
    sub_BAD700(
    (int)"!\"Error Decompressing data chunk.\"",
    (int)"D:\\jenkins\\workspace\\Code-CI-Releases-Public\\code\\HeroWars_clientServer\\Sources\\ReplaySystem\\ReplayServerConnection.cpp",
    6,
    (int)"Riot::Replay::ReplayServerConnection::GetChunk",
    (int)"Assert occurred, game may crash.");
    sub_9BB750("ReplayServerConnection GetChunk error. Error decompressing chunk data. Error: %d\n");
    }
  • Après enquête sur sub_B71120, j'ai localisé un appel qui finit par entrer dans une fonction assez importante. Cette fonction contient des chaînes comme:

    • "vérification d'en-tête incorrecte"
    • "méthode de compression inconnue"
    • "taille de fenêtre non valide"
  • Une recherche rapide sur Google de ces chaînes révèle ce qui suit: http://www.opensource.apple.com/source/zlib/zlib-22/zlib/inflate.c

  • J'ai également trouvé la référence de chaîne "1.2.3" dans un appel de fonction juste avant l'appel à la méthode inflate.c, ainsi qu'une autre référence "inflate 1.2.3 Copyright 1995-2005 Mark Adler". Il semble définitivement qu'ils utilisent la version 1.2.3 de Zlib pour la décompression des jetons. Je n'arrive tout simplement pas à les décompresser, quel que soit le décalage de fichier auquel je commence.

Mes questions)

Quelqu'un sait-il comment ces «jetons» peuvent être formatés ou s'il existe un type de compression / cryptage que je ne connais pas? Je soupçonne qu'il s'agit d'une forme compressée ou compressée des paquets Ethernet utilisés pendant la lecture en direct qui sont simplement lus en interne pour le client.

Alternativement, quelqu'un peut-il penser à une autre méthode pour supprimer ces données sans exécuter le client de jeu réel? Gardez à l'esprit que je voudrais récupérer simultanément les données de nombreux flux.


la source
1
La façon dont je pensais m'y prendre était de récupérer autant de fichiers de relecture de LOLReplay que possible et de simplement les crunch. Il y a, je pense, une archive ouverte où les gens peuvent télécharger leurs propres jeux, et je pense que le nouveau mode spectateur permet au client Replay de récupérer plus d'informations qu'auparavant.
Robert S.26
Quelles autres API et techniques existe-t-il? Pourquoi pensez-vous qu'il existe un cryptage? J'ai trouvé cela dans le GetGameMetaData: "encryptionKey": "" et "decodedEncryptionKey": ""
Nathan Goings
En tant qu'INF pour les personnes qui n'arrêtent pas d'atterrir sur cette question à partir de divers forums LoL, de voir mon nom sur le post sous "édité par" et de m'envoyer un e-mail pour poser des questions sur le sujet ... Je ne sais rien de LoL ou du format de ses flux. Veuillez ne pas m'envoyer un e-mail à ce sujet.

Réponses:

4

J'ai fait des recherches sur la même chose et j'ai trouvé ce dépôt extrêmement utile. Le fichier decrypt.rb déchiffre à la fois les blocs et les images clés.

Edit: consultez également ce fil reddit .

tyscorp
la source
Excellent. Le premier lien répond précisément à ma question. Le deuxième lien est également très utile. Merci beaucoup!