19 серпня 2009

Взлом "Счастливого Фермера"

Многие зарегистрированы на сайте В Контакте (если верить их данным, больше 40 миллионов). А среди них почти 6 миллионов играют в "Счастливого фермера". Эта статья предназначена для тех, кто хоть немного интересовался интерактивными играми В Контакте и имеет представление о HTTP запросах в браузере.
Меня, как программиста, в первую очередь интересовало написание программы, которая бы играла автоматически. Как-то раз я уже взломал приложение "Коктейль другу", "напоив" себя и друзей до отказа коктейлями (при чем, отправителя и коктейль можно было задать абсолютно любыми). Так, например, ради прикола напоил знакомую коктейлем "Рыжая шлюшка". Но в этом приложении всё было легко: id отправителя, получателя и коктейля были заданы прямо в запросе к серверу, без какой-либо авторизации и проверки на наличие средств на коктейль. Как побочный эффект, деньги снимались у получателя этих коктейлей.

Я пытался много раз взяться за "Счастливого фермера". Но раньше меня останавливала незнакомая мне библиотека AMFPHP, которая используется в этом приложении. Дело в том, что для написания роботов я всегда пользовался Firebug-ом (plugin-ом для Firefox). Этот плагин отображает все посылаемые серверу запросы и ответы сервера (с помощью этого плагина также можно определять ссылки на все видео и аудио, которые Firefox загружает на странице). Но в случае с AMFPHP Firebug при любом запросе отображал:

http://vkfarm.elex-tech.us/myfarm/data/gateway.php
amfphp and this gateway are installed correctly. You may now connect to this gateway from Flash.
AMF C Extension is loaded and enabled.
Note: If you're reading an old tutorial, it will tell you that you should see a download window instead of this message. This confused people so this is the new behaviour starting from amfphp 1.2.
View the amfphp documentation
Load the service browser

Именно это меня раньше и останавливало. Я долго не мог найти библиотеки, работающей с AMF. LupineDreamer посоветовал мне поискать среди framework-ов, в частности symfony и zend framework. В обоих framework-ах уже реализованы plugin-ы, работающие с AMF, и базируются они на библиотеке SabreAMF. Установил, разобрался в необходимых для моего скрипта вещах (кодирование своих данных для запроса на сервер, декодирование посланного на сервер запроса запроса).

Исходники "Фермера"
После первого запроса приложения на сервер возвращается некий secretid, который в последующих запросах передаётся на сервер в переменной auth или ca. Так же в последующих запросах на сервер посылаются переменные t и k, где t - локальное время, а k - MD5 подпись, сгенерированная приложением на основании id пользователя, t, auth и результата функции Encrypt.getKey (мне так и не удалось узнать, что она возвращает). Потратил много времени для поиска способа автоматической генерации k: искал на форумах, компилировал исходники - у меня результат функции Encrypt.getKey был всегда null, но, судя по всему, в приложении он не null. Привожу код, декомпилированный с помощью Flash Decompiler Trillix:

...
loc6 = getSystemTimestamp();
arg3["k"] = MD5.calcMD5(FarmModel.instance.uid + FarmModel.instance.authcode + Encrypt.getKey(Command) + loc6);
...

public class Encrypt extends Object
{
...
public static function getKey(arg1:Class):String
{
var loc2:*;
var loc3:*;
var loc4:*;
var loc5:*;
var loc6:*;
var loc7:*;
var target:Class;
var xml:XML;
var xmlList:XMLList;

xml = null;
xmlList = null;
target = arg1;
xml = describeType(target);
loc4 = 0;
loc5 = xml;
loc3 = new XMLList("");
for each (loc6 in loc5)
{
with (loc7 = loc6)
{
if (hasOwnProperty("@key"))
{
loc3[loc4] = loc6;
}
}
}
xmlList = loc3;
if (xmlList.length() > 0)
{
return xmlList[0].value;
}
return null;
}
...

Всех, кто добьётся хоть каких-то результатов в автоматической генерации k, большая просьба связаться со мной.
Без правильного ключа k сервер отдаёт ошибку "auth code error". Потому мне приходилось использовать значения k, t и auth, сгенерированные браузером. Как я уже говорил, Firebug не помогает при работе с AMFPHP. Потому я воспользовался другим приложением: Charles. Очень советую это приложение всем, кому нужно перехватывать запросы браузера. Вот только незарегистрированная версия работает 30 минут, потом приходится перезапускать. Из Charles я брал значеня k, t и auth, вставлял в свой скрипт, после чего получал возможность выполнять запросы. Но после выхода из аккаунта В Контакте или повторной загрузке страницы с приложением "Счастливый Фермер" ключи переставали быть действительными. Поскольку запуск Charles и копирование k, t и auth занимали много времени, я воспользовался другим способом: установил Tamper Data (plugin для Firefox), который перехватывает все запросы. Копировал запрос, содержащий k, t и auth в свой скрипт, потом с помощью SabreAMF вытягивал k, t и auth. Это занимало намного меньше времени, чем запуск Charles. Я думал, что большего не смогу добиться, но тут у меня появилась идея!

Plugin для Firefox
Да, идея до ужаса простая - написать plugin для , который будет сам отправлять мне запрос, содержащий k, t и auth. Потратив несколько дней, разобравшись с ANT-ом, XUL-ами, некоторыми class-ами и interface-ами компонентов Firefox, покопавшись в коде plugin-ов Tamper Data, LiveHTTPHeaders, QuickProxy, (потому не удивляйтесь, если вам покажется, что мой plugin вам покажется похожим визуально на QuickProxy и целый класс моего plugin-а взят из Tamper Data) мне удалось создать то, что я хотел. Итак, мой plugin в фоновом режиме запросы, посылаемые к приложению "Счастливый Фермер", а также некоторые настройки пересылает на мой сервер. На моём сервере сохраняются: id пользователя, k, t и auth, настройки пользователя. На сервере (на самом деле это мой локальный компьютер пока что) у себя я установил службу Cron NT service, которая периодически запускает робота на сервере. На данный момент робот на сервере проходит по всем друзьям пользователя и (в зависимости от настроек, выставленных в plugin-е) помогает (выпалывает, поливает грядки, уничтожает вредителей) и/или крадёт товар (фрукты, овощи, яйца, молоко). Робот работает только для тех пользователей, которых я сам добавлю в свою базу данных.

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

В дальнейшем планирую:
1. Увеличить объем возможностей робота (добавить кормление живности и т. д.)
2. Перенести всю серверную часть в plugin.