html текст
All interests
  • All interests
  • Design
  • Food
  • Gadgets
  • Humor
  • News
  • Photo
  • Travel
  • Video
Click to see the next recommended page
Like it
Don't like
Add to Favorites

All in по фану. Как разобрать, изменить и собрать обратно игру на Unity

Разработчики игр с удовольствием пользуются теми удобствами, что им предоставляет движок Unity, но, как выяснилось, он столь же удобен и для любого желающего вскрыть эти игры. Для примера я возьму Poker World и покажу на ней, как можно не только менять параметры, но и влезть в саму логику, переиначить все на свой лад и перепаковать APK. Заодно соберем небольшой набор утилит, который поможет в работе с мобильным софтом.

INFO

Все манипуляции с приложением делались исключительно в исследовательских целях и не преследуют финансовой выгоды в каком-либо виде.

Работа работой, а отдыхать тоже нужно. Человек я не азартный, но в карты покидать люблю. Недавно я приметил офлайновое приложение для игры в покер под названием Poker World. У него аскетичный интерфейс, минимальный набор функций, но есть почти все, что мне нужно. Напрягал только повышенный интерес разработчиков к донату. Поэтому с каждой раздачей исследовательская жилка напрягалась и таки не выдержала. Я взялся за клавиатуру с твердой уверенностью раздобыть себе немного виртуальных деньжат.

 
Первые шаги

Чтобы начать вивисекцию приложения нам понадобится небольшой стенд. В первую очередь стоит поставить нормальный эмулятор Android. Раньше я использовал Andy, но теперь он скурвился и даже начал пихать майнеры в свои дистрибутивы. Мне в срочном порядке пришлось искать замену. Моя основная ОС — Windows и поэтому все поиски были направлены на дистрибутивы для этой платформы. Я перебрал с десяток вариантов из топа выдачи Google, и все они, культурно выражаясь, оставляли желать лучшего. Однако мои молитвы были услышаны, и я наткнулся на Memu. На момент написания статьи последняя версия была 5.5.1. Тут есть все, что тебе может понадобиться. Создавать можно виртуальные машины Android версий 4.4 и 5.1, а также поддерживает эмуляцию нескольких моделей устройств.

Настройки эмулятора MEmu 5.5.1
Настройки эмулятора MEmu 5.5.1

Также тут присутствуют разные приятные фишки типа эмуляции камеры, спуфинга GPS, мак-адреса и сотового оператора, и, конечно же, есть поддержка трехмерной графики, то есть возможность запускать игры.

Что очень важно, MEmu поддерживает установку приложений из файлов APK и, о боги, в нем есть обычные настройки сетевого подключения Android. Это позволяет легко настроить устройство на работу через прокси типа Burp и перехватывать трафик. Ты удивишься, но часть эмуляторов не поддерживала работу через прокси и не имела стандартных сетевых настроек.

Главный экран эмулятора MEmu после запуска
Главный экран эмулятора MEmu после запуска

В общем, пока у меня не возникало претензий к MEmu. Если ты знаешь о более достойных вариантах, не стесняйся и пиши о них в комментариях.

Еще нам понадобится APK Studio, чтобы иметь возможность удобно распаковывать, пересобирать и подписывать пакеты. Для подписи пакетов к нему потребуется скачать uber-apk-signer и положить в директорию C:\Users\<имя_юзера>\.apkstudio\vendor, предварительно переименовав в uber-apk-signer.jar. Также можешь обновить apktool до последней версии и скопировать в ту же папку.

Главное окно утилиты APK Studio
Главное окно утилиты APK Studio

И, конечно же, само приложение. Его можно скачать из Play Market и App Store, но нам ведь нужен сам дистрибутив. Тут на помощь приходят сайты-агрегаторы приложений. Такого рода сервисы легко гуглятся по запросу apk download. Я, например, остановился на https://apkpure.com/, где помимо текущей версии приложения можно скачать и предыдущие (иногда бывает полезно).

Переходим по ссылке и скачиваем нашего подопытного. На момент написания статьи последняя версия приложения — 1.3.5.

Теперь можно установить скачанный apk в эмуляторе. Для этого достаточно перетащить его на окно с запущенным MEmu — практически в лучших традициях macOS.

Загрузка игры Poker World 1.3.5 в эмуляторе
Загрузка игры Poker World 1.3.5 в эмуляторе

На этом этапе базовые приготовления закончены. Обо всех остальных полезных штуках и утилитах я расскажу в процессе препарирования приложения.

 
Начинаем веселье в iOS

Так получилось, что играть я начал на айфоне. И где-то на третьем уровне денег начало катастрофически не хватать. Аппарат был без джейлбрейка, и делать мне его совершенно не хотелось, поэтому я начал искать баги в логике самого приложения. Такие, чтобы можно было провернуть, не закапываясь в его дебри.

Парочку таких я и обнаружил. В игре есть возможность раз в четыре часа крутить однорукого бандита, из которого тебе рандомно выпадают всякие ништяки. Их в игре всего два вида — это деньги и билеты. И те, и другие нужны для участия в турнирах. Так вот в местном аналоге тотализатора можно выиграть небольшое количество денег или один билетик. Количество денег, которые ты можешь срубить, зависит от уровня твоего персонажа. Каждые несколько уровней суммы выигрыша в этой рулетке удваиваются. На самом первом они составляют от $400 до $2000.

Своеобразный однорукий бандит в Poker World
Своеобразный однорукий бандит в Poker World

Про билет и 2000 баксов можно забыть, за месяц игры и тысячи кручений этой рулетки ни разу ничего подобного мне не выпало. Интересно будет взглянуть на алгоритм 🙂

Тем не менее, через пять таких спинов ты получаешь возможность сделать джекпот спин, в котором все выигрыши умножены на три и, соответственно, можно урвать аж три билета.

Эволюция спинов в Poker World
Эволюция спинов в Poker World

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

Чтобы бесконечно не переводить время в будущее, можно сделать так:

  • сворачиваем приложение, находясь на экране с таблицей спинов и таймером до следующего;
  • переводим часы на четыре часа вперед;
  • разворачиваем, видим, что появилась кнопка Spin Now. Нажимать ее не нужно;
  • сворачиваем;
  • переводим время на четыре часа назад;
  • снова разворачиваем и теперь уже нажимаем кнопку.


Я проводил такую процедуру после каждого джекпот спина. Это дает возможность не уходить далеко в будущее, так как от системного времени много чего зависит. Срабатывание алертов, событий в календаре и прочее.

Вообще, я сильно удивился тому, какие проблемы может вызвать изменение даты на устройстве с iOS. Например, после того как я выставил 2030, меня разлогинил iCloud и отказывался пускать обратно с неизвестной ошибкой. Я уж было подумал, что мой аккаунт заблокировали за путешествия во времени. Повторно авторизоваться удалось только после перезагрузки девайса.

INFO

Два года назад в iOS нашли баг: устройство окирпичивалось, если поставить дату на 1970 год. Можно предположить, что от системной даты многое зависит.

Плюс сама смена даты неудобна — чтобы сменить год, нужно прокрутить все 365 дней. Вот и сиди, вози пальцем как сумасшедший.

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

Эволюция бесплатных игр в Poker World
Эволюция бесплатных игр в Poker World

Ускорить можно точно таким же способом — изменение системного времени. К слову сказать, этот стандартный финт с переводом часов еще много где прокатывает, не стесняйся и чекай в тех приложениях, где предлагают чего-то подождать 🙂

Но это все цветочки. У меня завалялся старый джейлбрейкнутый айфон, а это значит, что настало время заглянуть поглубже в недра игры и посмотреть, что там творится. Запускаю утилиту Filza и смотрю, где располагаются файлы приложения. У меня это /path. Немного покопавшись, я обнаружил интересный файл com.youdagames.pokerworld.plist.

Интересный файл с настройками игры Poker World
Интересный файл с настройками игры Poker World

Сам файловый менеджер Filza позволяет открывать, редактировать и сохранять файлы plist. В нем располагаются разные настройки, которые касаются игры в целом и текущего пользователя, в частности. Мой взгляд зацепился за парочку интересных переменных с названиями — UserChips, UserTickets. И да, они означают именно то, что ты подумал. Это количество твоих денег (фишек) и билетов. Я поменял значения на нужные и запустил игру.

Редактирование количества денег и билетов у игрока в Poker World
Редактирование количества денег и билетов у игрока в Poker World
Добавили себе фишек и билетов
Добавили себе фишек и билетов

И вуаля! Виртуальный миллионер. Помимо этого в файле находится куча интересных параметров — таких как текущий уровень игрока, его позиция в десятке лидеров, какие уровни уже пройдены, лимиты столов и прочее. Если будет интересно, то можешь поэкспериментировать на досуге, а я перехожу к версии приложения для Android и более интересным вещам.

 
Властвуем в Poker World для Android

Первым делом точно так же проверяем домашнюю папку приложения. Не лежат ли там какие-нибудь интересные файлы? Для этих целей я воспользуюсь файловым менеджером из Cyanogen Mod и перейду в папку /data/data/com.youdagames.pokerworld/shared_prefs/.

Домашняя папка Poker World в Android
Домашняя папка Poker World в Android

Сразу же бросается в глаза файл com.youdagames.pokerworld.v2.playerprefs.xml. Откроем его и убедимся: там все то же самое, что и в iOS, только в формате XML.

Файл с настройками Poker World на Android
Файл с настройками Poker World на Android

Но мы это уже проходили, поэтому ценность этой находки для нас минимальна. Пойдем чуть дальше.

Попробуем декомпилировать apk-файл с игрой. Для этих целей я почти всегда использую замечательный онлайновый сервис javadecompilers.com/apk. Кстати, помимо приложений для Android, он может декомпилировать файлы JAR, причем разными методами. На выбор декомпиляторы JDCore, CFR, Jadx и т.д.

Возможные декомпиляторы на сайте javadecompilers.com
Возможные декомпиляторы на сайте javadecompilers.com

В общем, декомпильнули наш файл, скачали его, распаковали и видим, что ничего особо интересного там нет. Печаль.

Также есть целый фреймворк, который неплохо помогает в исследовании мобильных приложений, он называется Mobile Security Framework, MobSF. Он тоже выполняет декомпиляцию приложения и ищет в получившихся исходниках всякие интересные вещи и потенциальные уязвимости. Рекомендую не брезговать им и натравливать его на исследуемые приложения. Фреймворк легко устанавливается и, помимо этого, существует в виде контейнера Docker, что сводит его установку к одной команде.

> docker run -it -p 8000:8000 opensecurity/mobile-security-framework-mobsf:latest

Но нам это тоже не поможет 🙂 У нас здесь игра на движке Unity, на что недвусмысленно намекает наличие характерных файлов.

Игра Poker World написана на Unity
Игра Poker World написана на Unity

Я, конечно же, слышал про этот игровой движок, но никогда не приходилось иметь с ним дело в плане реверса. Немного покурив мануалы, я узнал, что все самое интересное обычно находится в файлах Assembly-CSharp.dll, Assembly-CSharp-firstpass.dll и Assembly-UnityScript.dll из папки Managed. Как видно из названия, они написаны на C#, поэтому нам нужен соответствующий декомпилятор. Есть несколько классных вариантов, среди них ILSpy и DotPeek. Обе утилиты абсолютно бесплатны и имеют свои фишки; я остановился на ILSpy. Откроем в нем Assembly-CSharp.dll и Assembly-CSharp-firstpass.dll.

Декомпиляция Unity файлов из Poker World в ILSpy
Декомпиляция Unity файлов из Poker World в ILSpy

Разворачиваем дерево файла Assembly-CSharp.dll и наблюдаем огромное количество классов с интересными названиями. Это абсолютна вся логика игры. Есть где развернуться!

Но как вносить изменения, чтобы можно было их сохранить? Первый вариант — это экспортировать исходники, отредактировать и попробовать скомпилировать их обратно в библиотеку. Думаю, что при таком раскладе понадобится устранить кучу зависимостей и возникнет немало подводных камней, которые отнимут значительное количество времени — результат просто того не стоит.

Сначала я было расстроился, но немного погуглив, я нашел отличное решение. При помощи утилиты под названием dnSpy мы можем вносить изменения напрямую в DLL, причем так, как если бы мы просто редактировали ее код на C#. Просто магия вне Хогвардса! 🙂

Скачиваем программу и открываем наши библиотеки в ней.

Декомпиляция файлов Unity из Poker World в dnSpy
Декомпиляция файлов Unity из Poker World в dnSpy

Если встроенный редактор покажется тебе недостаточно удобным, можешь сохранить все исходники как проект и пользоваться привычным. Для этого в меню File имеется команда Export to Project.

Сначала изменим что-нибудь простое, чтобы понять, сработает ли. Например, я нашел класс, который отвечает за отображение меню настроек игры. В нем есть метод Show(), который отрабатывает при нажатии на кнопку настроек.

/Assembly-CSharp/SettingsMenu.cs
088: // Token: 0x06001AE2 RID: 6882 RVA: 0x00079D30 File Offset: 0x00078130
089: public override void Show(params object[] args)
090: {
091:   base.Show(args);
092:   this.facebookText.text = this.GetFacebookText();
093:   base.StartCoroutine(this.Animate());
094:   this._data = GameManager.Instance.LoadSettings();
...
110:   string str = (!GameManager.Instance.cheatsEnabled) ? string.Empty : " | cheats";
111:   string str2 = (!GameManager.Instance.releaseBuild) ? " | debug" : string.Empty;
112:   this.version.text = "v" + Application.version + str2 + str;

Здесь задается переменная this.version.text, которая содержит номер текущей версии игры. Он выводится в левом нижнем углу на экране настроек.

Экран настроек в Poker World
Экран настроек в Poker World

Добавим к этой строчке что-нибудь свое. Для этого нужно кликнуть правой кнопкой мыши внутри метода и выбрать пункт меню Edit Method (C#) или просто нажать Ctrl-Shift-E.

Контекстное меню выбранного метода
Контекстное меню выбранного метода

Откроется окно для внесения изменений только в выбранный метод. Ты можешь выбрать Edit Class (C#) и редактировать весь класс целиком, но сейчас нам это не нужно.

Окно редактирования выбранного метода в dnSpy
Окно редактирования выбранного метода в dnSpy

Я добавил переменную str3, в которой написал небольшое приветствие.

/Assembly-CSharp/SettingsMenu.cs
111: string str2 = (!GameManager.Instance.releaseBuild) ? " | debug" : string.Empty;
112: string str3 = " | Hello from dnSpy";
113: this.version.text = "v" + Application.version + str2 + str + str3;

После этого нажимаем кнопку Compile. Тут компилятор может вернуть ошибки.

Ошибки компиляции метода в dnSpy
Ошибки компиляции метода в dnSpy

Не будем сильно вдаваться в суть ошибок; посмотрим лучше на место, где они обнаружились. Видишь то же самое имя файла, который мы редактируем, только с постфиксом g? Это означает global, то есть ошибки (по мнению компилятора dnSpy) содержит основной файл класса. Но мы ведь изменяем лишь один метод, а значит этими ошибками можно спокойно пренебречь. Поэтому двойным кликом по сообщению об ошибке, переходим в место, где они обитают, и просто комментируем неугодные строки.

Устраняем ошибки компиляции метода в dnSpy
Устраняем ошибки компиляции метода в dnSpy

После этих действий компиляция прошла успешно. Теперь можешь посмотреть в начало класса и заметить, что те строки, что мы комментировали, находятся в изначальном состоянии.

Состояние класса после рекомпиляции метода
Состояние класса после рекомпиляции метода

Метод перекомпилирован, теперь идем в меню File и выбираем Save Module.
Таким образом, у нас появилась обновленная DLL. Осталось собрать все обратно в APK, чтобы запустить на телефоне. Хоть APK — это обычный архив ZIP, но просто запаковать и изменить расширение недостаточно. Нужен верный манифест-файл и правильная подпись.

В этих делах нам поможет утилита apkstudio. Откроем APK с игрой и распакуем в какую-нибудь папку при помощи пункта меню File → Open → APK.

Меню File утилиты APK Studio
Меню File утилиты APK Studio

В опциях открытия файла в Project Path указываем путь, куда складывать распакованные данные. Также можешь убрать галочки с пунктов Decompile Source и Decode Resources, так как нам не нужно декомпилировать исходники и декодировать ресурсы приложения.

Настройки декодирования APK-файла
Настройки декодирования APK-файла

Теперь жмем Decode и переходим в папку с распакованным приложением. Копируем отредактированный DLL (Assembly-CSharp.dll) в /assets/bin/Data/Managed с заменой существующей. Снова идем в APK Studio и жмем F5 или выбираем пункт Build из меню Project. В директории, где лежит содержимое APK появился собранная версия. Но просто так установить ее не получится. Остался еще один шаг — подпись.

Сначала нужно сгенерировать ключ. Это можно сделать с помощью входящей в состав Java утилиты keytool. Для создания выполним следующую команду:

> keytool.exe -genkey -keystore <имя_контейнера> -storepass <пароль> -alias <имя_ключа> -validity <срок_действия_в_днях> -keyalg RSA -storetype pkcs12

Создание ключа для подписи APK
Создание ключа для подписи APK

Возвращаемся в APK Studio, переходим в меню Project → Sign/Export. Выбираем свежесозданный контейнер и указываем пароль к нему, название ключа и его пароль.

Выбор ключа для подписи APK
Выбор ключа для подписи APK

Нажимаем Sign. Программа немного подумает и скажет, что все прошло успешно.

Успешная подпись APK
Успешная подпись APK

Вот теперь можно устанавливать получившееся приложение. Запускаем его, переходим в настройки и видим, что наша строка красуется рядом с версией приложения.

Изменили логику работы приложения Poker World
Изменили логику работы приложения Poker World

Ну что, теперь пора браться за дела покруче, чем простое добавление строчек.
Немного побродив по исходникам, я наткнулся на интересные классы Cheat и CheatMenu. Это менюшка с читами и, судя по методам, есть очень интересные: выиграть текущую игру, показать карты соперников, выиграть текущую игровую зону.

/Assembly-CSharp/CheatMenu.cs
008: public class CheatMenu : MonoBehaviour
009: {
...
169:  public void WinPoker(int place)
...
189:  public void ShowCards()
...
199:  public void CompleteCluster(int clusterNumber)

Посмотрим в метод Start, чтобы узнать какой код выполняется при запуске

109: private void Start()
110: {
111:   this.Init();
112: }

В методе Init происходит инициализация меню.

079: private void Init()
080: {
081:   if (CheatCamera.instance == null)
082:   {
083:     return;
084:   }
085:   if (this.transformsToTouch == null || this.transformsToTouch.Length == 0 || this.transformsToTouch[0] == null)
086:   {
087:     this.transformsToTouch = CheatCamera.instance.transformsToTouch;
088:   }
089:   this.pointsToTouch = new Vector3[this.transformsToTouch.Length];
090:   for (int i = 0; i < this.pointsToTouch.Length; i++)
091:   {
092:     this.pointsToTouch[i] = this.transformsToTouch[i].position;
093:   }
094:   if (GameManager.Instance.releaseBuild)
095:   {
096:     base.gameObject.SetActive(false);
097:   }
098:   else if (GameManager.Instance.cheatsEnabled)
099:   {
100:     base.gameObject.SetActive(true);
101:   }
102:   else
103:   {
104:     base.gameObject.SetActive(false);
105:   }
106: }

Пробежавшись по коду, понимаем, что менюшка не работает на релизных версиях приложения. Досадно. Давай исправим это.

79: private void Init()
80: {
81:   if (CheatCamera.instance == null)
82:   {
83:     return;
84:   }
85:   if (this.transformsToTouch == null || this.transformsToTouch.Length == 0 || this.transformsToTouch[0] == null)
86:   {
87:     this.transformsToTouch = CheatCamera.instance.transformsToTouch;
88:   }
89:   this.pointsToTouch = new Vector3[this.transformsToTouch.Length];
90:   for (int i = 0; i < this.pointsToTouch.Length; i++)
91:   {
92:     this.pointsToTouch[i] = this.transformsToTouch[i].position;
93:   }
94:   base.gameObject.SetActive(true);
95: }

Однако просто активировать чит-меню недостаточно. Обрати внимание на метод Update.

104: private void Update()
105: {
106:   if (CheatCamera.instance == null)
107:   {
108:     return;
109:   }
110:   this.CheckTouches();
111: }

Каждый раз вызывается CheckTouches.

114: private void CheckTouches()
115: {
116:   if (Input.touchCount >= this.pointsToTouch.Length)
117:   {
118:     Touch[] touches = Input.touches;
119:     this.pointsTouched = new bool[touches.Length];
120:     for (int i = 0; i < touches.Length; i++)
121:     {
122:       Vector3 vector = CheatCamera.instance.GetComponent<Camera>().ScreenToWorldPoint(touches[i].position);
123:       Vector3 a = new Vector3(vector.x, vector.y, 0f);
124:       foreach (Vector3 b in this.pointsToTouch)
125:       {
126:         if (Vector3.Distance(a, b) <= 1f)
127:         {
128:           this.pointsTouched[i] = true;
129:         }
130:       }
131:     }
132:     for (int k = 0; k < this.pointsTouched.Length; k++)
133:     {
134:       if (!this.pointsTouched[k])
135:       {
136:         return;
137:       }
138:     }
139:     this.cheats.gameObject.SetActive(true);
140:     return;
141:   }
142: }

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

79: private void Init()
80: {
81:   if (CheatCamera.instance == null)
82:   {
83:     return;
84:   }
85:   if (this.transformsToTouch == null || this.transformsToTouch.Length == 0 || this.transformsToTouch[0] == null)
86:   {
87:     this.transformsToTouch = CheatCamera.instance.transformsToTouch;
88:   }
89:   this.pointsToTouch = new Vector3[this.transformsToTouch.Length];
90:   for (int i = 0; i < this.pointsToTouch.Length; i++)
91:   {
92:     this.pointsToTouch[i] = this.transformsToTouch[i].position;
93:   }
94:   base.gameObject.SetActive(true);
95:   this.cheats.gameObject.SetActive(true);
96: }

Сохраняем, билдим, подписываем, устанавливаем, запускаем и видим чит-меню. Можно убедиться, что все кнопочки рабочие.

Активированное чит-меню в Poker World
Активированное чит-меню в Poker World

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

Игра за столом Poker World
Игра за столом Poker World

В левом нижнем углу есть кнопочка с символом ?, которая показывает, какие карты были на руках в последней раздаче. Давай изменим ее функцию на показ карт соперников. Для этого найдем код, который отвечает за клик по этой кнопке.

/Assembly-CSharp/LastHandMenuButton.cs
05: public class LastHandMenuButton : MonoBehaviour
06: {
07:   // Token: 0x0600192D RID: 6445 RVA: 0x0006CF11 File Offset: 0x0006B311
08:   public void OnClick()
09:   {
10:     MenuManager.Instance.Show<LastHandMenu>(new object[0]);
11:   }
12: }

Пересобираем приложение и теперь при нажатии на нужную кнопку будут показываться карты противников.

Смотрим карты соперника в Poker World
Смотрим карты соперника в Poker World

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

 
Выводы

Благодаря таким манипуляциям можно «подправить» почти с любую игру, написанную на Unity, а это, как ты знаешь, очень и очень популярный движок. У dnSpy есть даже специальные билды библиотеки Mono.dll. Заменив оригинальную версию такой библиотеки, можно отлаживать приложение с помощью встроенного в dnSpy дебаггера. Очень удобная вещь.

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

Читать дальше
Twitter
Одноклассники
Мой Мир

материал с xakep.ru

2

      Add

      You can create thematic collections and keep, for instance, all recipes in one place so you will never lose them.

      No images found
      Previous Next 0 / 0
      500
      • Advertisement
      • Animals
      • Architecture
      • Art
      • Auto
      • Aviation
      • Books
      • Cartoons
      • Celebrities
      • Children
      • Culture
      • Design
      • Economics
      • Education
      • Entertainment
      • Fashion
      • Fitness
      • Food
      • Gadgets
      • Games
      • Health
      • History
      • Hobby
      • Humor
      • Interior
      • Moto
      • Movies
      • Music
      • Nature
      • News
      • Photo
      • Pictures
      • Politics
      • Psychology
      • Science
      • Society
      • Sport
      • Technology
      • Travel
      • Video
      • Weapons
      • Web
      • Work
        Submit
        Valid formats are JPG, PNG, GIF.
        Not more than 5 Мb, please.
        30
        surfingbird.ru/site/
        RSS format guidelines
        500
        • Advertisement
        • Animals
        • Architecture
        • Art
        • Auto
        • Aviation
        • Books
        • Cartoons
        • Celebrities
        • Children
        • Culture
        • Design
        • Economics
        • Education
        • Entertainment
        • Fashion
        • Fitness
        • Food
        • Gadgets
        • Games
        • Health
        • History
        • Hobby
        • Humor
        • Interior
        • Moto
        • Movies
        • Music
        • Nature
        • News
        • Photo
        • Pictures
        • Politics
        • Psychology
        • Science
        • Society
        • Sport
        • Technology
        • Travel
        • Video
        • Weapons
        • Web
        • Work

          Submit

          Thank you! Wait for moderation.

          Тебе это не нравится?

          You can block the domain, tag, user or channel, and we'll stop recommend it to you. You can always unblock them in your settings.

          • XakepVideo
          • часы
          • app store
          • клавиатура
          • приложения
          • домен xakep.ru

          Get a link

          Спасибо, твоя жалоба принята.

          Log on to Surfingbird

          Recover
          Sign up

          or

          Welcome to Surfingbird.com!

          You'll find thousands of interesting pages, photos, and videos inside.
          Join!

          • Personal
            recommendations

          • Stash
            interesting and useful stuff

          • Anywhere,
            anytime

          Do we already know you? Login or restore the password.

          Close

          Add to collection

             

            Facebook

            Ваш профиль на рассмотрении, обновите страницу через несколько секунд

            Facebook

            К сожалению, вы не попадаете под условия акции