Привет Хабр! Я думаю многие здесь знают про игру «Шарарам». А если не знаете то лучше не знать узнаете.

Я решил сделать персонально свой сервер этой игры.

Не смотря на то что возможно скорее всего для аудитории Хабра эта статья покажется банальной, но мне тупо негде это выложить на общее обозрение.

Инструменты


  • Любой браузер с инспектором
  • Adobe Flash Media Server (старую версию из 2009 так как новые не умеют в флэш. Спокойно ищется на всяких торрент трекерах) или Red5
  • Знание ECMAScript
  • Декомпиль флешек, я выбрал JPEXS Free Flash Decompiler потому что бесплатно
  • Adobe Flash Content Debugger

Логотип




Спасибо за логотип EarthShaker'у

Первые шаги


  1. Регаемся в игре
  2. Смотрим в инспекторе какой мусор нам шлет HTTP сервер
  3. Находим /async/ServerAction и радостно кликаем по добыче
  4. С удивлением обнаруживаем такую картину. В CDATA какая то муть шифрованная (благодаря друзьям-криптоманьякам выяснилось что это RC4)

Поиски ключа


Вроде бы все уже хорошо, но у нас нет ключа. Поэтому скачиваем base.swf из хтмл страницы игры и открываем его на обследование в декомпиль. Благодаря наличию Адоб Флэша я попробовал данный кусок кода

trace(_root);

который вернул _level0 в лог. Защита от школоанонимусов??

Угадываем что у Шарарама в качестве игрового сервера


Это было сделать не сложно. Всего лишь гуляем по исходникам и обнаруживаем файл FmsAPI. Гуглим че за FMS и…



это к сожалению не то, поэтому гугланём чё-то посерьезнее



Бинго, но я все еще сомневался, поэтому идем в Википедию.



Ну это уже серьезный аргумент. Можно уже 100% утверждать что это оно.

Бороздил гугл, оказалось что еще есть Red5 (да, я пытался сделать и на нем но чето дело не пошло).

Делаем сервак


Для начала напишем серверную сторону.

Мой php-говнокод для /async/* выглядит так (обьяснения в комментах в коде)

Большой фрагмент кода
<?php
// просто для эстетичности
header("Content-type: text/xml");
// включаем rc4 и остальные мелочи
include "crypto.php";
include "utils.php";
include "settings.php";

// смотрим че нас просят
switch ($_GET["action"]) {
   // инфа о юзере
    case 'ServerAction':
     // данные которые мы зашифруем и спакуем в CDATA-ноды
     // конфиг (впринципе можно и не редактировать)
        $config = '<config><item Id="1" Parameter="AccessRoleFlags" Value="0" Type="number" /><item Id="3" Parameter="IsPreloaderFast" Value="0" Type="bool" /><item Id="4" Parameter="InitialVolumeValue" Value="30" Type="number" /><item Id="6" Parameter="IsPreloaderEnabled" Value="1" Type="bool" /><item Id="7" Parameter="IsStartupHomeLocation" Value="0" Type="bool" /><item Id="8" Parameter="SwfVersion" Value="" Type="string" /><item Id="9" Parameter="SynchronizeAvatarRotation" Value="1" Type="bool" /><item Id="10" Parameter="StatisticsSendInterval" Value="0" Type="number" /><item Id="12" Parameter="LanguageId" Value="1" Type="number" /><item Id="13" Parameter="SnId" Value="1" Type="number" /><item Id="14" Parameter="IsInternational" Value="0" Type="bool" /><item Id="15" Parameter="AutoServerSelectionAllowed" Value="1" Type="bool" /><item Id="16" Parameter="DaysToFullSoil" Value="28" Type="number" /><item Id="17" Parameter="DaysToHalfSoil" Value="14" Type="number" /><item Id="18" Parameter="CurrentQuest" Value="421" Type="number" /><item Id="20" Parameter="TypeWeapon" Value="3" Type="number" /><item Id="21" Parameter="SkipTutorial" Value="1" Type="bool" /><item Id="23" Parameter="CurrentQuestGroup" Value="6161" Type="string" /><item Id="24" Parameter="IsNewRegistration" Value="1" Type="bool" /><item Id="25" Parameter="IsMotivatingAdsOn" Value="0" Type="bool" /></config>';
        
       // cписок серверов. можно либо вынести инфу о серве в другой файл
       // или редачить её тут
      // особый смысл имеют TRId (название сервера),  RTMPUrl (ссылка на сервер) и в принципе все. Остальное чисто косметическое.
            $serversList = '<servers><item Id="1" TRId="'.$gameServer_name.'" RId="5" RTMPUrl="rtmp://'.$gameServer_ip.':'.$gameServer_port.'/'.$gameServer_appname.'" Load="46" QuestLocationLoad="0" FriendsCount="0" ClubsCount="4" Weight="5.1" /></servers>';

         
       // айди, hwid (wtf??), тикет (для фронтэндеров - это типа JWT) и RoleFlags это типа кто юзер (картный, безкартный, модер, админ, etc)
        $userData = '<user UserId="1" hwId="'. getGUID() .'" ticketId="'. getGUID() .'" RoleFlags="2" />';
        // тут тоже особо ничего редачить не надо
        $system = '<system ServerDate="'.date('Y-m-d H:i:s').'" RPath="fs/3p897j5lf4e0j.swf" RVersion="56" />';
        // всякая инфа о юзере и наши CData которые мы шифруем прямо там
        echo '<?xml version="1.0" encoding="utf-8"?>
<response>
    <promotion>
        <i MRId="20106" State="1" />
        <i MRId="30896" State="7" />
    </promotion>
    <promotion_banner>
        <i MRId="30896" />
    </promotion_banner>
    <promotion_whats_new>
        <i Id="386" TypeId="1" MRId="20143" />
        <i Id="611" TypeId="2" MRId="27179" />
        <i Id="784" TypeId="2" MRId="30841" />
        <i Id="785" TypeId="2" MRId="30895" />
        <i Id="786" TypeId="2" MRId="30897" />
    </promotion_whats_new>
    <preloader>
        <i MRId="30894" ShowTime="20;00" />
    </preloader>
    <sn_status IsBinded="0" />
    <phone>
        <messages/>
    </phone>
    <user_name Value="test" />
    <postcard>
        <messages/>
    </postcard>
    <licence_promotion>
        <item Id="1" GroupId="0" OrderId="0" MRId="14763" />
        <item Id="2" GroupId="0" OrderId="1" MRId="14764" />
        <item Id="3" GroupId="0" OrderId="2" MRId="14765" />
        <item Id="4" GroupId="1" OrderId="0" MRId="14766" />
        <item Id="5" GroupId="1" OrderId="1" MRId="14767" />
        <item Id="6" GroupId="1" OrderId="2" MRId="14768" />
        <item Id="7" GroupId="2" OrderId="0" MRId="20597" />
        <item Id="8" GroupId="2" OrderId="1" MRId="20598" />
        <item Id="9" GroupId="2" OrderId="2" MRId="20599" />
    </licence_promotion>
    <flags EntranceCount="2600" />
    <tutorial>
        <item Id="-1" State="1" />
        <item Id="1" State="1" />
        <item Id="2" State="1" />
        <item Id="3" State="1" />
        <item Id="4" State="1" />
        <item Id="5" State="1" />
    </tutorial>
    <miniquest>
        <i Id="148515433" MiniquestId="90004" IsPostponed="0" StartDate="2018-06-06T18:58:28.113">
            <i Id="298265808" TaskId="900041" IsFinished="0" Counter="3" />
            <i Id="298265809" TaskId="900042" IsFinished="0" Counter="0" />
            <i Id="298265810" TaskId="900043" IsFinished="1" Counter="0" />
        </i>
    </miniquest>
    <grants ReceivingCount="0" />
    <requests ReceivingCount="0" />
    <cdata value="'. encrypt($config) .'" />
    <cdata value="'. encrypt($system) .'" />
    <cdata value="'. encrypt($userData) .'" />
    <cdata value="'. encrypt($serversList) .'" />
</response>';
        break;
  // простой php-пинг
    case 'Ping':
        echo '<response isPong="true" />';
        break;
    // add more below
    default:
        echo "<!-- there's nothing -->";
        break;
}
?>


В файле settings.php это

<?php

// php settings
error_reporting(E_ERROR | E_PARSE);

// server settings
$gameServer_ip = "127.0.0.1";
$gameServer_port = 1935;
$gameServer_name = 202; // check http://sharaball.ru/fs/3p897j5lf4e0j.swf for strings you can use (also, you can edit this file in any SWF editor)
$gameServer_appname = "shararam"; // название инстанса на стороне fms

?>

В файле utils.php это

<?php

// http://guid.us/GUID/PHP
function getGUID(){
        $charid = strtoupper(md5(uniqid(rand(), true)));
        $hyphen = chr(45);// "-"
        $uuid = substr($charid, 0, 8).$hyphen
            .substr($charid, 8, 4).$hyphen
            .substr($charid,12, 4).$hyphen
            .substr($charid,16, 4).$hyphen
            .substr($charid,20,12);
        return $uuid;
}
?>

В crypto.php это

Большой фрагмент кода

<?php

	 function rc4( $key_str, $data_str ) {
      // convert input string(s) to array(s)
      $key = array();
      $data = array();
      for ( $i = 0; $i < strlen($key_str); $i++ ) {
         $key[] = ord($key_str{$i});
      }
      for ( $i = 0; $i < strlen($data_str); $i++ ) {
         $data[] = ord($data_str{$i});
      }
     // prepare key
      $state = array( 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,
                      16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,
                      32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,
                      48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,
                      64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,
                      80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,
                      96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,
                      112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,
                      128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
                      144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
                      160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,
                      176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,
                      192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,
                      208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,
                      224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,
                      240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255 );
      $len = count($key);
      $index1 = $index2 = 0;
      for( $counter = 0; $counter < 256; $counter++ ){
         $index2   = ( $key[$index1] + $state[$counter] + $index2 ) % 256;
         $tmp = $state[$counter];
         $state[$counter] = $state[$index2];
         $state[$index2] = $tmp;
         $index1 = ($index1 + 1) % $len;
      }
      // rc4
      $len = count($data);
      $x = $y = 0;
      for ($counter = 0; $counter < $len; $counter++) {
         $x = ($x + 1) % 256;
         $y = ($state[$x] + $y) % 256;
         $tmp = $state[$x];
         $state[$x] = $state[$y];
         $state[$y] = $tmp;
         $data[$counter] ^= $state[($state[$x] + $state[$y]) % 256];
      }
      // convert output back to a string
      $data_str = "";
      for ( $i = 0; $i < $len; $i++ ) {
         $data_str .= chr($data[$i]);
      }
      return $data_str;
   }

function encrypt($str){
	return bin2hex(rc4("_level0", $str));
}
?>


Мой htaccess


Options +FollowSymLinks
RewriteEngine On
RewriteBase /
RewriteRule ^async/(.*) asyncController.php?action=$1


Код сервера


Это уж слишком старый образец, там уже было шифрование в rc4 на сервере, я новый потерял поэтому придется показать вам этот ужас.

H2CA разбивает строку в массив чтобы сервер её скушал, такова обсфукация

Большой фрагмент кода

/*
* RolyPolyWorld Server Code
* by Semen Elkin, 2018
*/

function H2CA(hex) {
 var _loc3_ = [];
 var _loc1_ = hex.substr(0, 2) != "0x" ? 0 : 2;
 while (_loc1_ < hex.length) {
  _loc3_.push(parseInt(hex.substr(_loc1_, 2), 16));
  _loc1_ = _loc1_ + 2;
 }
 return _loc3_;
}
Client.prototype._LS = function(descriptor, startPoint, startState) {
 return "";
}

Client.prototype._NSF = function() {
 return "";
}

Client.prototype.$ = function(CMD, srvName, _unknown, __unknown, callback) {
 trace("CMD: " + CMD);
 if (CMD == "_I") {
  // return UserInitData
  return [H2CA("e4ba5848485429d25723c62654510684f67e7b2cffb0debd608de7bca09d0b10f8a0c511b52c5fb57adc0321b8edef0b0cde086422a751a8604104a1d6b5bd050e19ac989ec6f44ff7f6998af46ffac822fe0673c54823fd8b1744f6b09907cb69e703cc4941ca27c0783ea6085f35eaf0614ba95507eeca1e2662d40c43857b0fa1cc045851c6a3d8e81cac73468c7ed174731c50b2141576a808f7a4cb7026e2253ebff413b1a3bc5907c9a13783dd8cdeccf636c48720cea4cf3040eb339a4329ca4c731218719e9366d6ce24ec2fee9f67ca586bdf0c6764051deb33972c640a6775bb206c707003e22e078ef18e77faf6e84423332f4212a2ae12ba56a537f05fac4fa7598487dd138396db4db00a85c28a533d3a2645f00fa2a0b1c4ffdd5b5d015c935909e23950a63ae37f2d1345d86296470633f47d8b9c6c423a2d429e6b06b596b4c914cf12b850640aa91f51d456994dc57c2a4cb32116b5b4c4a1d5768eecfa2e158d4c42f64294793c0da42bc5c949ae7f0501b488906bb4609c0443c7c8d3b675605762aec6dcda5b813f3abcf8ec8706c137889c0809bfd90c1e191aacc84d35317b2418e6cfc8429d1f0b0532b0e4ff0e1c57f8a46c64f806cc8b1509691b0266b921f61d670a73480c4e83935438e9f1a84708f755ab3e66e78a6ae3d2a88ee3e8083a994e6212162d388a6df2f100e11ea5d2367b8c016804790cbbb4bcadd1f415dddd8814672a235a6a7236521010596a0abe0e8d8ba9930e4c85c103d8dc12439482c6bde7d215b2f43dd20a3862f191fb134d8a590dda31ddbe4575a197db52170715c6e302038554c953c8a6875a26240452c75e19ba0fdac1c6894a134bb998011fd88b1c175face045a7d192159d84c1d848996a367055c0b5b5efad7827d3dc3e9dd3c361cbc59c915089ed79768f9e1cf6ad60acbd7e418e6c0dfb63389135745bcdb45fb1c83b6471223f0e00f09203f6a580ae863c2c7c1ecd7f8117daa623868e5f040e74ce8c409e2d26ae0b51f8f4c1dfb15114098aa3f7f38703d53d1654d393ae82d6b65a19a0c782373789c9b6f55bfddd224e977bcf8b15a810f5d0888380d4543361c7daaf12f3cdc02f098f044a04c47996439820d82a22dc8439e0a0470cf4989dae13a827fb946ef29271ead58ae31934ba490492f4d4f97a440c3b1983e9eb431050f1e14ead8ac032973ffad1a257cd652976ec9d8a4c8c480be6b254ad017d6e8d25c97edd6723880a50f94860fbc0b5bbd6b9234971a251fd351d17bc12ebf71b47f72c2c393e2d79be2779d27612522942a5629c453f6063c4905d5b64749c1690dd2d918bf7845cba8ff3d9b0726dd724641926f6493a1438af12f1263cf8e9781ef5ac8e9ac4ce63db2e8b2761431d0fdc1f70f8b75908f597697aeaef3849e2b525681d13d493707e45f40f07461cea503ba038ec76981a6abf733bea79eff7121b97515943196417660fb854e43fba68d2bfbb5fc5ecf66f2cfffa9c62dd60731d4f92be76d63da3f4f19ad1a7b41ff7bdcf4c7e6e5629c475b0fed66768681f76d5bab4287c355eb951953a3795d381afed2aed639782fda5377c23d67d90c3f6f5fcea5c41a5567082c32cfb4886fe63aec9a6373ce924072fab5ff340b415470e8d973da687319b9259ccf0ebd78b2c2d05453463f7efb8278188b5a9e6fef9b9c26051af9295521015ec19a8997cd76903e65eca7a2538ff2c4c07f6df5e951485242f171f07bc72f99a69fcd3119dabfaf3e4be78264a32d0f82d2de290ec62b4ed5b9d1db59d42e9ab41bad695ff25a47271cae2ca52013743cf8b72c3315896e65a0f8158ac9b92a010002d4b846d0c984274e65be446e237397633929bd1fdfceeca06deeaa33f6097b8a203042ff8a72d342061487e2a335a688d28334b87313709bd0cc0f99d6dcc961f9f4d628d812a2bb4478263817a714cf9fd50423f28c70c1ed03222764630faf695da3936aa384315b63d2b9b44f1c911df43fba1f8353787eee6ab2be85ae010c2cfd60ce3c8522cdc32df85202abafa4925bea3bf2c5766dfb0f56e0e882847d57ff9e4c9df52b8652319a3008e22becc5a162fb5e90ca62f961f42e342003d0ca98d48eaafa9a698be8734e42db75befc380ff67cdecdc8297315bda07f1c9eebda90ecc128f01e7187eb14971541da50b7878e897bea0ac8ebefd3a4115b3e21a0bc07dd92f5050fca020e63a3c8a9d123327fb8d0200f4d85892cc906bc1f4865e8c75d0b68a43f54e0204d3a18886e125a478a6da9129e5f79f4f4bbb4f4385d84aa3392d752c44dadbdca771a8a8202a22631e02559b7deb2e8f8aaa52eef394")];
 } else if (CMD == "_UFG") {
  // Friends list get
  return ""; quests
 } else if (CMD == "_UFR") {
  // Friends requests get
  return "";
 } else if (CMD == "_CM") {
  // GetClubMap
  return "<clubmap />";
 } else if (CMD == "_SNFP") {
  // GetFriendPanelData
  return '<root><L4><i UserId="3490071" UserName="56" AvatarUrl="https://sharaball.ru/shimg?u275AF9B0E0FB47AE" IsOnline="true" Level="59" RoleFlags="2" IsHomeLocked="true" /><i UserId="22033" UserName="UberSoldat" AvatarUrl="https://sharaballru/shimg?u7705945283620CEC" IsOnline="true" Level="50" RoleFlags="2" IsHomeLocked="false" /><i UserId="26514836" UserName="953" AvatarUrl="https://sharaballru/shimg?u70A0C3FFDC2AE686" IsOnline="true" Level="44" RoleFlags="0" IsHomeLocked="true" /><i UserId="4294784" UserName="-22" AvatarUrl="https://sharaballru/shimg?uA0F2D2940A2C0680" IsOnline="false" Level="66" RoleFlags="0" IsHomeLocked="true" /><i UserId="6514777" UserName=" 7" AvatarUrl="https://sharaballru/shimg?u7633EEBAAC8D8750" IsOnline="false" Level="62" RoleFlags="0" IsHomeLocked="true" /><i UserId="15918373" UserName="Gamer9999" AvatarUrl="https://sharaballru/shimg?u3F6E105179A94CF9" IsOnline="false" Level="60" RoleFlags="2" IsHomeLocked="false" /><i UserId="5499397" UserName="2014" AvatarUrl="https://sharaballru/shimg?uFAA76A3F45E04650" IsOnline="false" Level="59" RoleFlags="0" IsHomeLocked="true" /><i UserId="6765542" UserName="2399" AvatarUrl="https://sharaballru/shimg?uBC8AF14DC9568867" IsOnline="false" Level="57" RoleFlags="0" IsHomeLocked="true" /><i UserId="6091024" UserName="60" AvatarUrl="https://sharaballru/shimg?u6254ABCD6C72BA40" IsOnline="false" Level="55" RoleFlags="0" IsHomeLocked="true" /><i UserId="5335890" UserName="992" AvatarUrl="https://sharaballru/shimg?uB51CD240A8D9A6F8" IsOnline="false" Level="54" RoleFlags="0" IsHomeLocked="true" /><i UserId="7403986" UserName="" AvatarUrl="https://sharaballru/shimg?uAFC6BB4C6CB5523B" IsOnline="false" Level="54" RoleFlags="0" IsHomeLocked="true" /><i UserId="3711098" UserName="12345x" AvatarUrl="https://sharaballru/shimg?u30D03C19372FD998" IsOnline="false" Level="53" RoleFlags="0" IsHomeLocked="true" /><i UserId="2477499" UserName="" AvatarUrl="https://sharaballru/shimg?u2FDDD1060A5F77A4" IsOnline="false" Level="52" RoleFlags="0" IsHomeLocked="true" /><i UserId="6881717" UserName="" AvatarUrl="https://sharaballru/shimg?uA1B439427D7B3055" IsOnline="false" Level="52" RoleFlags="0" IsHomeLocked="true" /><i UserId="3747929" UserName="329" AvatarUrl="https://sharaballru/shimg?uC60A8606BA6F5F20" IsOnline="false" Level="51" RoleFlags="0" IsHomeLocked="true" /><i UserId="491914" UserName="votetu" AvatarUrl="https://sharaballru/shimg?uF843320FF79B6387" IsOnline="false" Level="48" RoleFlags="0" IsHomeLocked="true" /><i UserId="5143339" UserName=" 908" AvatarUrl="https://sharaballru/shimg?u2521238E5E881E10" IsOnline="false" Level="48" RoleFlags="0" IsHomeLocked="true" /><i UserId="7164879" UserName="SuperKohka" AvatarUrl="https://sharaballru/shimg?uDF898434F4FA678A" IsOnline="false" Level="48" RoleFlags="0" IsHomeLocked="true" /><i UserId="21200791" UserName="Alsoa" AvatarUrl="https://sharaballru/shimg?uA418D0DB845DEDF5" IsOnline="false" Level="48" RoleFlags="2" IsHomeLocked="false" /><i UserId="28287949" UserName="630" AvatarUrl="https://sharaballru/shimg?uF02BE2EAF00206CF" IsOnline="false" Level="48" RoleFlags="2" IsHomeLocked="true" /><i UserId="6858621" UserName="200125" AvatarUrl="https://sharaballru/shimg?u02E14C376A340686" IsOnline="false" Level="46" RoleFlags="0" IsHomeLocked="true" /><i UserId="5116798" UserName=" 2" AvatarUrl="https://sharaballru/shimg?uBD09B4CE3AE8832A" IsOnline="false" Level="43" RoleFlags="0" IsHomeLocked="true" /><i UserId="6858399" UserName="wosso" AvatarUrl="https://sharaballru/shimg?uD2CABA24168A42DD" IsOnline="false" Level="43" RoleFlags="0" IsHomeLocked="true" /></L4></root>';
 } else if (CMD == "_D") {
  // UpdateUserData
  return {
   callback_uid: callback
  };
 } else if (CMD == "_LG") {
  // GetLocation
  return '<location ID="28" IsHome="0" IsClub="0" IsLocked="0" IsVisaAccessPermitted="1" MediaResourceID="30644" x="550.0" y="380.0" Name="test">   <options>     <Constraints>       <item ID="0" Type="Q" QuestId="390" StepId="23" StateCode="1" Equally="1" Value="2" RoomState="0" />    </Constraints>  </options>  <object ID="28002" AObjectTypeId="2" AObjectId="61" AObjectRefId="25" MediaResourceID="30648" x="634.0" y="197.0" />   <object ID="28003" AObjectTypeId="2" AObjectId="70" AObjectRefId="19" MediaResourceID.="30645" x="674.0" y="227.0" />   <object ID="28004" AObjectTypeId="2" AObjectId="71" AObjectRefId="30" MediaResourceID="30647" x=".135.0" y="153.0" />   <object ID="28010" AObjectTypeId="2" AObjectId="532" AObjectRefId="54" MediaResourceID="3587" x="130.0" y="33.0.0">     <options>       <override AObjectTypeId="18" />       <conditions>        <User IsSecretAgent="1" />      </conditions>     </options>  </object>   <object ID="28733" AObjectTypeId="2" AObjectId="733" AObjectRefId="6" MediaResourceID="30646" x="490.0" y="120.0" /> </location>';
 } else if (CMD == "_UOG") {
  if ( __unknown == "whats_new_data"){
    return "1|2|3";
  } else if ( __unknown == "pet_battle_news"){
    return "1|2|3";
  } else {
    trace("_UOG OPTION " + __unknown);
  }
 } else if (CMD == "_UOS") {
  // SetUserOption
 } else if (CMD == "_GOGI") {
  // GetGroupObjectInfo
  return '<group_object UOGId="-6163" ObjectGroupId="6163" ObjectGroupTypeId="101" ControllerType="4" Stored="0" ContorollerMRId="30781"> <item Id="6163001" AObjectId="828" AObjectTypeId="2" AObjectRefId="27" MediaResourceID="30775" LocationId="19" X="284" Y="136" IsActive="1" IsInterractable="1" /> <item Id="6163002" AObjectId="3193" AObjectTypeId="50" MediaResourceID="30373" LocationId="27" X="295" Y="332" Frame="F$0" IsActive="1" IsInterractable="1" /> <item Id="6163003" AObjectId="3194" AObjectTypeId="50" MediaResourceID="30774" LocationId="85" X="475" Y="303" Frame="F$0" IsActive="1" IsInterractable="1" /> <item Id="6163004" AObjectId="3195" AObjectTypeId="50" MediaResourceID="30776" LocationId="85" X="116" Y="123" Frame="F$0" IsActive="1" IsInterractable="1" /> <item Id="6163005" AObjectId="3196" AObjectTypeId="50" MediaResourceID="30777" LocationId="85" X="282" Y="100" Frame="F$0" IsActive="1" IsInterractable="1" /> <item Id="6163006" AObjectId="3197" AObjectTypeId="50" MediaResourceID="30778" LocationId="85" X="453" Y="160" Frame="F$0" IsActive="1" IsInterractable="1" /> </group_object>';
 } else if (CMD == "_ULNS") {
  // SetUserLastNewspaper
  return "asd";
 } else if (CMD == "_DA") {
  return '<kek> <ID>1</ID> <IsSecretAgent>1</IsSecretAgent> <IsMember>1</IsMember> <IsPresent>1</IsPresent> <IsActive>1</IsActive> <Units>5</Units> <MessageID>2</MessageID> </kek >';
 } else {
  trace("Unknown command: " + CMD);
 }
}
Client.prototype._SCD = function(callback) { // get server time
 return 123;
}


application.onConnect = function(client) {
 this.acceptConnection(client);
}


XML который мы шлем серверу выглядит так. Ничего особенного.

<userInitData>
    <user Id="1" RoleFlags="2" Level="100" PositiveEnergy="11" IsMinorSecretAgent="1" MagicTickets="999" UsualTickets="999" />
</userInitData>
<account>
    <PhoneCardBalance>123</PhoneCardBalance>
    <WeaponsCount>2</WeaponsCount>
    <OxigenUnits>5</OxigenUnits>
</account>
<secret_agent>
    <StartDate>000</StartDate>
    <Number>123</Number>
    <Interval>2</Interval>
</secret_agent>
<user_avatar></user_avatar>
<smiles>
    <Id>1</Id>
</smiles>
<pets />
<pet_battle_places></pet_battle_places>
<user_magic_abilities>
    <Id>1</Id>
    <ExpirationDate>DATE</ExpirationDate>
    <IsLimited>false</IsLimited>
</user_magic_abilities>
<user_phone>
    <BufferSize>1</BufferSize>
    <SkinMediaResourceID>112</SkinMediaResourceID>
    <PhoneId>2</PhoneId>
    <Balance>999</Balance>
</user_phone>
<quests>
    <Id>148515433</Id>
    <StateCode>90004</StateCode>
    <UpdateDate>2018-06-06T18:58:28.113</UpdateDate>
    <RecordDate>2018-06-06T18:58:28.113</RecordDate>
    <StartDate>2018-06-06T18:58:28.113</StartDate>
    <LastFinishedStep>0</LastFinishedStep>
    <GamesScore>0</GamesScore>
    <GamesCount>0</GamesCount>
    <TeleportId>0</TeleportId>
    <MRId>1</MRId>
    <IconMRId>5</IconMRId>
    <EndDate></EndDate>
</quests>
<questgamedata></questgamedata>
<magiclessons></magiclessons>
<ufoquestinfo></ufoquestinfo>
<res_objects></res_objects>
<actions></actions>
<spend_cones></spend_cones>
<options></options>
<mission_dobject></mission_dobject>
<smiles></smiles>
<positive_energy></positive_energy>
<giftbox_digger></giftbox_digger>
<object_groups></object_groups>
<game_award_pack></game_award_pack>
<sn_og_status></sn_og_status>
<notices></notices>
<controller></controller>
<bonus_day></bonus_day>
<informer_bonus></informer_bonus>
<nift></nift>
<sharagent></sharagent>
<stpack></stpack>
<yavideo></yavideo>

Встретимся в следующем эпизоде!

Комментарии (2)


  1. VBKesha
    16.10.2018 22:57
    +1

    Ставлю плюс, хотя думаю это не спасет. ИМХО код надо убрать под спойлеры хотя бы, а лучше на гитхаб. И анализа когда, или хотя бы его его запрос-ответов надо поболее, а так я тут набросал вот это, оно как то работает, не красиво.


  1. poloart
    18.10.2018 10:28

    Я не могу никак повлиять на репутацию других и пишу один пост в день, но такие посты на хабре я очень люблю. Вот причины
    1. Это старый хабр
    2. Это исследование того, что «какбе» скрыто
    3. Я ничего не знал про игру Шарарам и вряд ли узнаю, но…

    Сам этот пост всего лишь то, что я хочу видеть на хабре. Я хочу читать про новые технологии (подробно!), про исследование того, что «скрыто», про умных людей, про подробные гайды в изложении «для всех» и так далее.

    Я не хочу видеть на хабре опусы а-ля алазара — убейся об стол!!! И другой «копирайтинг/копипаст» того материала, что я уже прочитал или могу прочитать на ресурсах вроде «газета.ру» и прочих популярных сми.

    Мне нужен (а своё мнение вы можете оставить несколько ниже, или просто повесить шпалу — вы ж это тут так любите, шпала без камента, это ж прям черта хабраюзера, зашпалил и в норку) материал чуть ниже или чуть выше уровня обывателей.