Игровой Центр@Mail.Ru

в 6:56, , рубрики: Mail.ru Games, php, warface
Здравствуй! Мой прошлый пост «Как мы читы разрабатывали или кого сгубила жадность» вызвал у многих мракобесие, и в одном из советов от меня требовали конкретики. Требовали — держите мануал о том, как можно заменить Игровой Центр Mail.Ru(заодно расскажу про систему авторизации в Игровом Центре Mail.ru). Поехали!

Что нам понадобится?

Во-первых, нам нужен сервер с установленным на него PHP.
Во-вторых, нам нужна Visual Studio для разработки на C#
В-третьих, как можно было догадаться, нам нужна ОС Windows.

Разберемся с авторизацией Игрового Центра

(далее ГЦ)

1. Первым делом ГЦ отправляет на сервер запрос с логином/мэйлом и паролем пользователя(обращается к php-скрипту).
2. В ответе скрипт отсылает xml-данные в виде simple-xml, содержащий GcToken
3. ГЦ отправляет второй запрос на сервер параметром GcAuth
4. В ответе скрипт отсылает xml, содержащий SessionKey, Uid, Token, MinVersion и Timestamp
5. ГЦ запускает игру с Токеном, номером сервера и Uid

Начинаем разработку

Сначала напишем веб-интерфейс для управления программой

Создаем простую html-страничку с кнопкой «Start» и пишем JS-код для отправки POST-запросов и получения данных.

<html>
    <head>
       <title>Центр Игр</title>
       <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
       <script type="text/javascript">
function gcauth(){
  $.post("gcauth.php", { email: "тут email", password: "тут пароль" }, // Авторизуемся как ГЦ
  function(data){
    var str = data.replace('"','');
    var spl = str.split(""%"");
    var gcToken = spl[2];
    //var uid = spl[1];
    //alert();
    $.post("autologin.php", { gctoken: gcToken }, // Уже с токеном ГЦ авторизуемся в игре
      function(logindata){
        logindata = logindata.split("%");
        var uid = logindata[0];
        var token = logindata[1];
        var link = "starter:" + logindata+";";
       window.location.href = link;
       //alert(link);
      })
  });
}
	</script>
    </head>
    <body>
       <button onclick="gcauth()">Start</button>
    </body>
</html>

Регистрируем протокол, по которому будем осуществлять связь с программой

Создаем файл starter.reg
REGEDIT4

[HKEY_CLASSES_ROOTstarter]
@="URL:Starter Protocol"
"URL Protocol"="starter"

[HKEY_CLASSES_ROOTstartershell]

[HKEY_CLASSES_ROOTstartershellopen]

[HKEY_CLASSES_ROOTstartershellopencommand]
@=""C:\GameCenter@Mail.Ru.exe" "%1""

Откроем файл и добавим данные в реестр

Пишем клиентское приложение на C#

1.Создаем новый проект Windows Forms в Visual Studio
2. Редактируем файл Program.cs

using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Windows.Input;

namespace WindowsFormsApplication1
{
    static class Program
    {
        /// <summary>
        /// Главная точка входа для приложения.
        /// </summary>
       static String ProcessInput(string s)
       {
           return s;
       }
       [STAThread]
       private static void Main(string[] args) //объявляем параметры(аргументы)
       {
           Application.EnableVisualStyles();
           Application.SetCompatibleTextRenderingDefault(false);
           foreach (string s in args)
           {
               string[] arguments; // параметры
               string[] arr; // массив
               string uid; // ID юзера
               string token;// токен(уникальный ключ)
               arguments = ProcessInput(s).Split(':');
               arr = arguments[1].Split(',');
               uid = arr[0];
               token = arr[1];
               /*- Далее добавляем переменные среды, если их не существует -*/
               if (Environment.GetEnvironmentVariable("GC_PROJECT_ID") == null)
                   // GC_PROJECT_ID 1177
                   Environment.SetEnvironmentVariable("GC_PROJECT_ID", "1177");
               if (Environment.GetEnvironmentVariable("GC_TYPE_ID") == null)
                   // GC_TYPE_ID 0
                   Environment.SetEnvironmentVariable("GC_TYPE_ID", "0");
               if (Environment.GetEnvironmentVariable("GC_PIPE_NAME") == null)
                   // GC_PIPE_NAME GameCenterV3
                   Environment.SetEnvironmentVariable("GC_PIPE_NAME", "GameCenterV3");
               if (Environment.GetEnvironmentVariable("GC_GCLAY_PATHNAME") == null)
                   // GC_GCLAY_PATHNAME C:...LocalMail.RuGameCenterGCLay.dll
                   Environment.SetEnvironmentVariable("GC_GCLAY_PATHNAME", @"Путь к GameCenterGCLay.dll"); // Здесь указываем путь к GCLay.dll
               if (Environment.GetEnvironmentVariable("CHROME_ALLOCATOR") == null)
                   // CHROME_ALLOCATOR TCMALLOC
                   Environment.SetEnvironmentVariable("CHROME_ALLOCATOR", "TCMALLOC");

               Environment.SetEnvironmentVariable("MOZ_CRASHREPORTER_DATA_DIRECTORY", "");
               Environment.SetEnvironmentVariable("MOZ_CRASHREPORTER_RESTART_ARG_0", "");
               Environment.SetEnvironmentVariable("MOZ_CRASHREPORTER_STRINGS_OVERRIDE", "");
               Process.Start("C:\GamesMailRu\Warface\Bin32Release\Game.exe", "--shard_id=0 +online_server s0.warface.ru -uid "+uid+" -token "+token); // Запускаем Warface с параметрами
               MessageBox.Show("Click [OK] to close"); // Тормозим завершение программы
           }
       }
    }
}

Настраиваем серверную часть

Пишем PHP-скрипты для получения токенов и т.д.

*Мы не будем снифферить отправляемые и принимаемые заголовки, а используем те, которые уже были получены

Создаем файл gcauth.php

<?php
header('Content-type: text/html; charset=utf-8');
// вход в систему
// имя хоста, куда будем заходить
$hostname = 'authdl.mail.ru';
$email = $_POST['email'];
$password = $_POST['password'];
// инициализация cURL
$ch = curl_init('https://'.$hostname.'/ec.php?hint=GcAuth');
// получать заголовки
curl_setopt ($ch, CURLOPT_HEADER, 1); 
// если ведется проверка HTTP User-agent, то передаем один из возможных допустимых вариантов:
curl_setopt ($ch, CURLOPT_USERAGENT, 'Downloader/4000');
// елси проверятся откуда пришел пользователь, то указываем допустимый заголовок HTTP Referer:
curl_setopt ($ch, CURLOPT_REFERER, $hostname);
// использовать метод POST
curl_setopt ($ch, CURLOPT_POST, 1);
// сохранять информацию Cookie в файл, чтобы потом можно было ее использовать
curl_setopt ($ch, CURLOPT_COOKIEJAR, 'cookie.txt');
// передаем поля формы
curl_setopt ($ch, CURLOPT_POSTFIELDS, '<?xml version="1.0" encoding="UTF-8"?><GcAuth Username="'.$email.'" Password="'.$password.'" ChannelId="0"/>');
// возвращать результат работы
curl_setopt ($ch, CURLOPT_RETURNTRANSFER, 1);
// не проверять SSL сертификат
curl_setopt ($ch, CURLOPT_SSL_VERIFYPEER, 0);
// не проверять Host SSL сертификата
curl_setopt ($ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/x-www-form-urlencoded'));
// это необходимо, чтобы cURL не высылал заголовок на ожидание
// выполнить запрос
curl_exec ($ch);
// получить результат работы
$result = curl_multi_getcontent ($ch);
$data = curl_exec($ch);
$xml = htmlspecialchars($result);
preg_match('/SessionKey=["']?([^"' ]*)["' ]/is',$xml,$sessionKeyArr); // Выделяем SessionKey из ответа регулярками
preg_match('/Uid=["']?([^"' ]*)["' ]/is',$xml,$uidArr); // То же самое с ID юзера
preg_match('/Token=["']?([^"' ]*)["' ]/is',$xml,$tokenArr); // ... с Токеном
preg_match('/MinVersion=["']?([^"' ]*)["' ]/is',$xml,$minVersionArr); // Минимальная версия, нам это не понадобится
//preg_match('/Timestamp=["']?([^"' ]*)["' ]/is',$xml,$timestampArr); // Время, нам тоже не нужно
$SessionKey = str_replace(""", "",$sessionKeyArr[1]);
$Uid = str_replace(""", "",$uidArr[1]);
$Token = str_replace(""", "",$tokenArr[1]);
$replace_quotes = array('"', "'");
$MinVersion = str_replace($replace_quotes, "", $minVersionArr[1]);
/*- Выводим данные -*/
echo $SessionKey;
echo "%";
echo $Uid;
echo "%";
echo $Token;
echo "%";
echo trim($MinVersion);
//echo $Timestamp;
//echo $xml;
//echo $matches;
// закрыть сессию работы с cURL
curl_close ($ch);
?>

Теперь создадим autologin.php

<?php
header('Content-type: text/html; charset=utf-8');
$GcToken = $_POST['gctoken'];
// вход в систему
// имя хоста, куда будем заходить
$hostname = 'authdl.mail.ru';
// инициализация cURL
$ch = curl_init('https://'.$hostname.'/sz.php?hint=AutoLogin');
// получать заголовки
curl_setopt ($ch, CURLOPT_HEADER, 1); 
// если ведется проверка HTTP User-agent, то передаем один из возможных допустимых вариантов:
curl_setopt ($ch, CURLOPT_USERAGENT, 'Downloader/4000');
// елси проверятся откуда пришел пользователь, то указываем допустимый заголовок HTTP Referer:
curl_setopt ($ch, CURLOPT_REFERER, $hostname);
// использовать метод POST
curl_setopt ($ch, CURLOPT_POST, 1);
// сохранять информацию Cookie в файл, чтобы потом можно было ее использовать
curl_setopt ($ch, CURLOPT_COOKIEJAR, 'cookie.txt');
// передаем поля формы
$postfield = '<?xml version="1.0" encoding="UTF-8"?><AutoLogin ProjectId="1177" SubProjectId="0" ShardId="0" GcToken="'.$GcToken.'"/>';
curl_setopt ($ch, CURLOPT_POSTFIELDS, $postfield);
// возвращать результат работы
curl_setopt ($ch, CURLOPT_RETURNTRANSFER, 1);
// не проверять SSL сертификат
curl_setopt ($ch, CURLOPT_SSL_VERIFYPEER, 0);
// не проверять Host SSL сертификата
curl_setopt ($ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/x-www-form-urlencoded'));
// это необходимо, чтобы cURL не высылал заголовок на ожидание
// выполнить запрос
curl_exec ($ch);
// получить результат работы
$result = curl_multi_getcontent ($ch);
$data = curl_exec($ch);
$xml = htmlspecialchars($result);
preg_match('/PersId=["']?([^"' ]*)["' ]/is',$xml,$persIdArr); // Выделяем PersId из массива полученных данных
preg_match('/Key=["']?([^"' ]*)["' ]/is',$xml,$keyArr); // то же самое с Key
$PersId = str_replace(""", "",$persIdArr[1]);
$Key = str_replace(""", "",$keyArr[1]);
/*- Выводим полученные данные -*/
echo $PersId;
echo "%";
echo $Key;
// закрыть сессию работы с cURL
curl_close ($ch);
?>

Теперь осталось лишь залить все на сервер и испытать. На время написания статьи могла быть написана какая-либо проверка еще на что-то.

Спасибо за прочтение мануала. Надеюсь, в чем-то я вам помог, удачи!

Разработчикам Mail.Ru советую доработать клиентское приложение, чтобы исходящие соединения не показывались.

Автор: nikita_arut

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js