Здравствуй! Мой прошлый пост «Как мы читы разрабатывали или кого сгубила жадность» вызвал у многих мракобесие, и в одном из советов от меня требовали конкретики. Требовали — держите мануал о том, как можно заменить Игровой Центр 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