...

пятница, 18 апреля 2014 г.

[Из песочницы] И снова Dripstat!

Этот пост навеян вот этим постом: тыц.

Прочитал я его и подумал, неужели подобным образом автоматизируются браузерные процессы?

Кликер — это как-то слишком прямолинейно, и не подобают труъ программерам подобные автоматизации)

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

image



Итак, начнем разбираться:



1. Поверхностный анализ протокола обмена сообщениями между сервером и клиентом показал что подмену сообщений произвести не получится — сервер имеет внутренние механизмы верификации.



Неужели? Смотрим внимательно в код и видим, действительно, объекты шифруются каким-то XORCipher…

Но разве нам это нужно? Смотрим метод отправки события на сервер,

— в него приходит объект события,

— шифруется,

— отправляется на сервер


Анализируем объект события до шифрования, это простой json:


{ userid: "userid", events: [ массив событий ] }


Сами события содержат информацию

— о накопленном количестве памяти

— о прошедшем времени (это вообще гениально)

— о покупках


Немного модифицировав этот метод мы можем добиться того, что

— сервер будет думать, что прошло много времени с последнего сохранения (опытным путем было выяснено, что это значение не может быть больше двух минут)

— изменить обработку ошибок (чтобы не перезагружать страницу в случае чего)


Итак, приступим собственно к написанию майнера

План

— Запуск, конфигурация

— Периодичное сохранение. Здесь я предпочел «скользящий» режим setTimeout, потому как с setInterval неизбежен завал при лагах сети

— Откат к последнему валидному состоянию в случае ошибки валидации (слишком жадные :) )


Конструктор:



function Miner(incr, dripK, delay) {
var that = this;
this.incr = incr || localStats.bps*1e3; // сколько памяти добываем за одну итерацию
this.dripK = dripK || 0.5; // коэффициент сливания памяти
this.delay = delay || 100; // задержка между итерациями
document.hasFocus = function () {return true;};
NO_PINGY=1; // На проекте включен сбор статистики движений мышем, отключаем

// Redefine postEvent
RestEventManager.prototype.postEventData = function(e,t,next) // Тут добавили параметр next, для замыкания цикла
{
var r=XORCipher.encode(DataSaver.key,JSON.stringify(e)); // Вот оно, шифрование!
// Собственно запрос:
return $.ajax({type:"POST",async:!0,url:GAME_URL+(loggedIn?"events":"eventsanon"),data:r,contentType:"text/plain",
success: function() {
var self = this;
that.lastCorrect = localStats.byteCount; // Сохраняемся
t.apply(self, arguments); // Родной callback
setTimeout(function(){
if(localStats.byteCount > localStats.memoryCapacity * that.dripK) $('#btn-addGlobalMem').trigger('click'); // Сливаем память
}, 0);
if(typeof next == 'function')next();
},
error: function(e) {
localStats.byteCount = that.lastCorrect; // Откат
console.error(e.responseText); // show error text
if(typeof next == 'function') next(); // собственно, следующая итерация
}})
}
}


Далее, нам нужно построить событие:



Miner.prototype.postEvent = function(mem, time, next) {
var d = {
userid: networkUser.userId,
events: [{
generatedMem: mem,
power: null,
timeElapsed: time,
type: 1
}]
}
RestEventManager.prototype.postEventData(d, function(){}, next);
};


Готово.


Обвязываем запуск/остановку:



Miner.prototype.start = function() {
var that = this;
this.stopped = false;
this.lastCorrect = localStats.byteCount; // save before the action
function post(){
localStats.byteCount+=that.incr; // mine some bytes
that.postEvent(localStats.byteCount, 120000, function(){ // tell to server that 2minutes passed
if(!that.stopped)
that.sI = setTimeout(post, that.delay); // next iteration on response
})
}
if(this.sI) clearTimeout(this.sI);
if(!this.stopped)
this.sI = setTimeout(post, this.delay); // first call
};

Miner.prototype.stop = function() {
this.stopped = true;
};


Запускаем!



var miner = new Miner();
miner.start();



Тут стоит заметить, что валидация накопленных Вами байтиков зависит от Вашей «способности генерировать», т.е. количества приобретенных агрегатов. Поэтому на старте я приобретаю, по 1 штуке всех девайсов, и штук 50-60 кластеров, постепенно повышая/играясь со скоростью добычи…


Результат: за полчаса написания и 4-5 часов работы скрипта вывел в топ 1-2 два аккаунта arth/Arth :)



ЗЫ: Инвайт, конечно хотелось бы, но после семи постов в песочнице я уже практически смирился с read-only. :(


ЗЗЫ: При попытке сохранения этого поста, получаю ошибку



{"system_errors":["SQLSTATE[HY000]: General error: 1364 Field 'description' doesn't have a default value"]}




Неожиданно для хабра)

This entry passed through the Full-Text RSS service — if this is your content and you're reading it on someone else's site, please read the FAQ at http://ift.tt/jcXqJW.


Комментариев нет:

Отправить комментарий