Wprowadzenie
Bawiłem się z systemem obserwacyjnym LoL w nadziei, że w końcu skrobię dane ze strumieni i zbuduję z nich zestaw danych do analizy. Rozumiem, że istnieją już pewne nieoficjalne interfejsy API i techniki, ale szukam naprawdę konkretnych wydarzeń w grze (zabójstwa bohaterów, zabójstwa z wieżyczek, puchazy przedmiotów, zabójstwa w dżungli, koledzy mistrzów dla określonych wydarzeń itp.).
Co do tej pory wymyśliłem
Kiedy zaczynasz obserwować grę (w NA), twój klient łączy się z następującym hostem:
spectator.na.lol.riotgames.com:8088
Zakładam, że ten host jest wspierany przez Amazon AWS lub podobny. W każdym razie następną rzeczą, która się dzieje, jest wysłanie przez klienta żądania wersji do serwera Spectate:
GET / tryb obserwatora / rest / konsument / wersja
Zwraca to niezależnie od bieżącej wersji serwera widza. Np .: „1,80,54”
Następnie klient wysyła żądanie metadanych gry:
GET / tryb obserwatora / rest / Consumer / getGameMetaData / NA1 / [gameid] / [some random nonce] / token
Zwraca metadane dotyczące gry. Przykład tych danych: http://pastebin.com/3N4qs0hx
Klient zna teraz parametry, według których sesja obserwacyjna powinna się rozwijać. Próbuje zlokalizować najnowszą porcję danych, wywołując:
GET / tryb obserwatora / rest / Consumer / getLastChunkInfo / NA1 / [gameid] / 30000 / token
Próbka tych danych: http://pastebin.com/Cj7dEAr9
Po zidentyfikowaniu fragmentów danych są one proszone:
GET / tryb obserwatora / rest / Consumer / getGameDataChunk / NA1 / [gameid] / [token #] / token
Próbka danych tokena (plik binarny przekonwertowany na heksadecymalny): http: // pastebin.com / GyqPRP5J
Gra przełącza się między wywołaniem getLastChunkInfo i getGameDataChunk, gdy dane stają się dostępne ze strumienia powtórek. Istnieje również połączenie, które występuje po przechwyceniu około 5 części do następujących elementów:
GET / tryb obserwatora / rest / Consumer / getKeyFrame / NA1 / [gameid] / [somechunkid] / token
Uważam, że to połączenie występuje tylko przy uruchomieniu powtórki i za każdym razem, gdy użytkownik szuka innej godziny.
Wiem, że gra używa szyfrowania na pewnym poziomie. Uważam, że jest to Blowfish ECB z faktycznym kluczem określonym w wierszu poleceń. Próbowałem odszyfrować te tokeny za pomocą klucza sesji, ale nadal wyglądają dość losowo.
Edytuj 23.03.2013
- Stwierdziłem, że tokeny najprawdopodobniej nie są szyfrowane przez modyfikację argumentu wiersza poleceń zawierającego klucz i ponowne uruchomienie gry z debuggera (poprawnie załadował powtórkę).
Żetony wydają się być skompresowane. Istnieje wywołanie podprogramu, który jeśli zwróci liczbę całkowitą niezerową, wywoła następujące czynności:
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"); }
Po zbadaniu sub_B71120 zlokalizowałem wywołanie, które ostatecznie wchodzi w dość dużą funkcję. Ta funkcja zawiera ciągi znaków takie jak:
- „nieprawidłowe sprawdzenie nagłówka”
- „nieznana metoda kompresji”
- „nieprawidłowy rozmiar okna”
Szybkie wyszukiwanie tych ciągów w Google ujawnia: http://www.opensource.apple.com/source/zlib/zlib-22/zlib/inflate.c
Znalazłem również odwołanie do łańcucha „1.2.3” w wywołaniu funkcji tuż przed wywołaniem metody inflate.c, a także inne odwołanie „inflate 1.2.3 Copyright 1995-2005 Mark Adler”. Wygląda na to, że używają Zlib w wersji 1.2.3 do dekompresji tokenów. Po prostu nie mogę ich zdekompresować, niezależnie od tego, od jakiego przesunięcia pliku zacznę.
Moje pytania)
Czy ktoś wie, jak te „tokeny” mogą zostać sformatowane lub czy istnieje jakiś rodzaj kompresji / szyfrowania, o którym nie wiem? Podejrzewam, że są to niektóre skompresowane lub spakowane pakiety ethernetowe używane podczas gry na żywo, które są po prostu odtwarzane wewnętrznie klientowi.
Alternatywnie, czy ktoś może pomyśleć o innej metodzie skrobania tych danych bez uruchamiania rzeczywistego klienta gry? Pamiętaj, że chciałbym pobierać dane z wielu strumieni jednocześnie.