Во многих социальных сетях, в том числе в ВКонтакте, с некоторых пор стало проводиться множество конкурсов с ценными призами. Речь пойдет о подделке результатов с точки зрения организатора, а конкурсы - те, в которых победитель определяется случайным образом из списка участников.
Итак, существует множество сервисов, которые помогают в проведении сферического конкурса, а доказательством зачастую является записанное видео или прямой эфир, в процессе которого происходит выбор победителя. Давайте рассмотрим, как можно организовать тривиальную подмену результатов, ничем себя не выдав. В качестве примера я рассмотрю вариант с использованием random.org (тот случай, когда организатор генерирует последовательно несколько случайных чисел, чтобы определить страницу и порядковый номер участника на странице), а также вариант с использованием Random.app.
Для начала давайте определимся, как вообще можно провести незаметную подмену в прямом эфире. Самое первое, что приходит в голову: перехватить и модифицировать запросы с помощью промежуточного прокси-сервера (например, Fiddler или Charles), модифицировать результат непосредственно в браузере (например, с помощью Greasemonkey или Tampermonkey), сделать визуальную копию необходимого ресурса на локальном сервере и заворачивать запросы на него с помощью hosts-файла или своего DNS-сервера, и так далее. В конце концов, можно что угодно "нарисовать", если речь идет о видеозаписи проведения конкурса. Остановимся на варианте с модификацией результата в браузере с помощью Tampermonkey или Greasemonkey. На мой взгляд этот вариант наиболее простой для реализации и понимания.
Берем Google Chrome и ставим в него Tampermonkey (есть в Chrome Web Store). В "я без понятия, как это место называется" панели появится новая иконка.
Приступим, для начала random.org. Заходим на сайт и видим в правой части True Random Number Generator, который обычно и используется.
После беглого изучения мы видим, что этот элемент представляет собой iframe, который загружается по ссылке вида:
1 |
https://www.random.org/widgets/integers/iframe.php?title=True+Random+Number+Generator&buttontxt=Generate&width=160&height=200&border=on&bgcolor=%23FFFFFF&txtcolor=%23777777&altbgcolor=%23CCCCFF&alttxtcolor=%23000000&defaultmin=1&defaultmax=100&fixed=off |
Пройдя по ссылке мы можем увидеть, что основная логика реализована в файле iframe.js, после изучения логики становится очевидно, что при нажатии кнопки Generate шлется http-запрос к random.org с желаемым диапазоном, которые возвращает случайное число из диапазона и выводится с помощью вызова функции printNumber из iframe.js. Давайте реализуем простую подмену результата.
Нажмем по вышеупомянутой иконке Tampermonkey и выберем пункт Add a new script. Откроется редактор, куда вы можете сразу скопировать данный скрипт (не забыв после этого нажать кнопку Save):
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 |
// ==UserScript== // Название, версия скрипта и URL, в контексте которого скрипт будет автоматически запускаться // @name Random.org // @version 0.1 // @match https://www.random.org/* // ==/UserScript== // Число, которым мы хотим заменить результат var desired_number = 31337; // На каком по счету нажатии произвести замену var desired_click_number = 3; var click_ctr = 0; // Проверяем, что функция printNumber определена if (typeof printNumber != "undefined") { // Сохраняем printNumber под другим именем и переопределяем её var origPrintNumber = printNumber; printNumber = function() { // Ведем учет кол-ва вызовов функции и подменяем результат на нужном по счету click_ctr++; if (click_ctr == desired_click_number) document.getElementById("true-random-integer-generator-result").innerHTML = desired_number; else origPrintNumber(); } }; |
Как видите - скрипт достаточно простой. В текущем варианте, на 3 по счету нажатии кнопки Generate, мы увидим результат 31337, независимо от заданного диапазона. Чтобы сбросить счетчик нажатий, достаточно перезагрузить страницу в браузере.
Теперь давайте проведем беглый анализ Random.app.
Мы имеем дело с приложением для ВКонтакте, которое тоже встраивается с помощью iframe. Приложение использует VK API и не взаимодействует с социальной сетью для получения списка возможных победителей. Победитель выбирается случайным образом простым вызовом Math.random. С основной логикой работы Random.app можно ознакомиться, пролистав содержимое следующих скриптов: main.js, random.models.js, random.views.js. Приведу небольшие фрагменты кода, которые отвечают за интересующие нас действия:
main.js
1 2 3 4 5 6 |
$(document).on('click', '.roll-roulette', function () { // console.log(usersArray); var id = Math.floor((Math.random() * usersArray.length)); view.setWinner(usersArray[id]); view.resizeWindow(); }) |
random.view.js
1 2 3 4 5 6 |
setWinner: function(user){ $('.winner .photo a').attr('href','http://vk.com/id'+user.uid); $('.winner .photo img').attr('src',user.photo_big); $('.winner .name').html(user.first_name + ' '+ user.last_name); this.resizeWindow(); } |
Мы видим, что на элемент с классом .roll-roulette (кнопка Выбрать победителя) вешается обработчик, который выбирает случайного пользователя из заранее сформированного списка и вызывает функцию setWinner, которая отображает победителя. Что ж, давайте сделаем простой скрипт, скопировав часть логики с сайта автора:
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 |
// ==UserScript== // @name Random.app // @version 0.1 // @match *://pliashkou.com/* // Воспользуемся JQuery для упрощения некоторых действий // @require https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js // ==/UserScript== // ID победителя var winnerUid = [75292250]; // Добавляем свой обработчик для кнопки Выбрать победителя $(document).on ( 'click', '.roll-roulette', function () { // Воспользуемся методами Random.app для получения необходимых данных от VKontakte // По сути мы просто получаем фамилию, имя и адрес фотографии для отображения var view = new CommonView(); var users = new Users(); users.options.from = 0; users.options.limit = 1; users.get ( { uids: winnerUid, fields: 'uid, first_name, last_name, photo_big' }, // Выводим победителя, как только получим данные от VK API function (users) { view.setWinner(users[0]); view.resizeWindow(); } ); } ) |
Всё опять-таки крайне тривиально, теперь при нажатии кнопки мы всегда будем получать человека с желаемым ID в качестве победителя. Естественно, никто не мешает добавить дополнительной логики в скрипт, чтобы выигрывали не только "избранные", но кому это надо...
Остается еще один простой момент: по-умолчанию в Chrome видна кнопка расширения Tampermonkey и зрители могут что-то заподозрить - не вопрос, нажимаем правой клавишей по ней и выбираем пункт Hide button.
Подведем итоги. Я разобрал часто встречающиеся примеры, однако, ими дело не ограничивается. Еще существуют ресурсы, которые после проведения розыгрыша предоставляют ссылку на результат, чтобы пользователи могли пройти по ней и убедиться что всё честно, но, вы же понимаете, что ресурсом владеют простые люди, а договориться можно с кем угодно. Хотя, пожалуй, можно верить таким ссылкам с random.org (вроде бы доступно только для владельцев платных аккаунтов), но другие ресурсы под большим вопросом, ведь кто мешает, например, мне создать очередной сайт для проведения розыгрышей, раскрутить его и выиграть там, где мне это интересно.
Update (29.01.2017)
Обновленная версия скрипта для Random.app:
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 |
// ==UserScript== // @name Random.app // @version 0.2 // @match *://pliashkou.com/* // Воспользуемся JQuery для упрощения некоторых действий // @require https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js // ==/UserScript== // ID победителя var winnerUid = [75292250]; var f_ptr = VK.api; vk_api = function(method, options, callback) { if(method == 'getProfiles') { // Если запрашивается информация об одном победителе if(options.uids.indexOf(',') == -1) options.uids = winnerUid.shift(); } return f_ptr(method, options, callback); }; // Добавляем свой обработчик для кнопки Выбрать победителя $(document).on ( 'mouseover', '.btn-default', function () { // Переопределяем метод VK.api VK.api = vk_api; } ); |
Update (04.03.2018)
Скрипт для Randstuff.ru:
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 |
// ==UserScript== // @name Randstuff.ru // @version 0.1 // @match http://randstuff.ru/* // @run-at document-end // @grant none // ==/UserScript== var desired_number = 31337; var desired_click_number = 3; var click_ctr = 0; $.ajaxPrefilter ( function(options, originalOptions, jqXHR) { var originalSuccess = options.success; options.success = function (data) { click_ctr++; if(click_ctr == desired_click_number) data.number = desired_number; originalSuccess(data); }; } ); |
Скрипт для Randomizer:
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 |
// ==UserScript== // @name Randomizer // @version 0.1 // @match *://im-brand.ru/* // ==/UserScript== var bReplacePhoto = false; var winnersList = [ ['Максим Антонов', 'https://pp.userapi.com/c638823/v638823253/43120/RuiiVVlULKc.jpg'], ['Петр Андреев', 'https://pp.userapi.com/c638823/v638823253/43120/RuiiVVlULKc.jpg'], ['Илья Новиков', 'https://pp.userapi.com/c638823/v638823253/43120/RuiiVVlULKc.jpg'] ]; var getWinnerHTMLPtr = getWinnerHTML; getWinnerHTML = function(winner) { if(winnersList.length > 0) { var currentWinner = winnersList.shift(); var userName = currentWinner[0].split(" "); winner.first_name = userName[0]; winner.last_name = userName[1]; if(bReplacePhoto) winner.photo_50 = currentWinner[1]; } return getWinnerHTMLPtr(winner); }; |
Update (04.06.2018)
Скрипт для Random.app:
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 |
// ==UserScript== // @name Random.app // @version 0.3 // @match https://s3.eu-central-1.amazonaws.com/randomapp* // @require https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js // ==/UserScript== // ID победителя var winnerUid = [75292250]; var f_ptr = VK.api; vk_api = function(method, options, callback) { if(method == 'getProfiles') { if(options.uids.indexOf(',') == -1) options.uids = winnerUid.shift(); } return f_ptr(method, options, callback); }; $(document).on ( 'mouseover', '.btn-default', function () { VK.api = vk_api; } ); |
Скрипт для Randomizer:
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 |
// ==UserScript== // @name Randomizer // @version 0.2 // @match *://shilov.app/* // ==/UserScript== var bReplacePhoto = false; var winnersList = [ ['Максим Антонов', 'https://pp.userapi.com/c638823/v638823253/43120/RuiiVVlULKc.jpg'], ['Петр Андреев', 'https://pp.userapi.com/c638823/v638823253/43120/RuiiVVlULKc.jpg'], ['Илья Новиков', 'https://pp.userapi.com/c638823/v638823253/43120/RuiiVVlULKc.jpg'] ]; var getWinnerHTMLPtr = getWinnerHTML; getWinnerHTML = function(winner) { if(winnersList.length > 0) { var currentWinner = winnersList.shift(); var userName = currentWinner[0].split(" "); winner.first_name = userName[0]; winner.last_name = userName[1]; if(bReplacePhoto) winner.photo_50 = currentWinner[1]; } return getWinnerHTMLPtr(winner); }; |
Скрипт для Randstuff.ru:
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 |
// ==UserScript== // @name Randstuff.ru // @version 0.2 // @match *://randstuff.ru/* // @run-at document-end // @grant none // ==/UserScript== var desired_number = 31337; var desired_click_number = 3; var click_ctr = 0; $.ajaxPrefilter ( function(options, originalOptions, jqXHR) { var originalSuccess = options.success; options.success = function (data) { click_ctr++; if(click_ctr == desired_click_number) data.number = desired_number; originalSuccess(data); }; } ); |
Update (24.11.2018): Решил выкладывать скрипты на сторонний сервис: https://greasyfork.org/en/users/228137-kaimi (доступны актуальные версии для сервисов Random.app, Random.org и Randstuff.ru).
тоже надо
Здравствуйте. Тоже очень ждем скрипта , думаю что там не сложно поправить , всю суть что сделали опишу.
Там где прежде было приложение было полностью обновлено, а старую версию с которой мы работали перенесли на новую ссылку https://vk.com/app6108296
Обновлено на Greasyfork
Все круто , олично работает
Как выиграть вот на этом сайте lizaonair.com, будет ли сложно написать к нему похожий скрипт?)
Здравствуйте, меня интересует и нужна помощь, проведён конкурс и хочется узнать куда смотреть, где произошёл обман ? Было в контакте с рандомом .
Вот ссылка https://vk.com/video-104233048_456239074?api_access_key=a38d309620c7f2dde4
Сложно сказать, в принципе, если скрыть плагин, чтобы он не отображался в окне браузера, то не определишь.
Да и скрипты для tampermonkey - это не единственный способ.
Спасибо за статью! Подскажите, пожалуйста, что нужно дописать в скрипте для рандом орг, чтобы было одновременно 5 чисел на подмену. Заранее спасибо!
Подряд или случайное из 5 чисел бралось?
Можно убрать проверку счетчика нажатий, сделать desired_number массивом и брать из него подряд или в случайном порядке числа.
Можно вопрос? как сделать чтобы был не один человек, а 2 и больше?
Переписать код соответствующим образом.
https://learn.javascript.ru/
Здравствуйте. Есть актуальная ссылка для скачивания скприпта? На том сайте выдаёт ошибку 404
Да вроде https://greasyfork.org/en/users/228137-kaimi работает
Каими, огромное спасибо за код, очень выручил. Но назрел вопрос, как переписать его, что б он подряд выбирал нужных победителей.
не работает эта ссылка
Здравствуйте, подскажите, пожалуйста как это сделать? Чтобы desired_number был массивом..
Взять в квадратные скобки, перечислить значения через запятую, элемент получать через shift.
Понял, спасибо, а еще такой вопрос: " if (click_ctr == desired_click_number)"
Мне нужно с этим что-то делать? Т.к я убираю же этот самый счетчик нажатий..
Можно убрать, если предполагается с первого значения выдавать то, что требуется. Можно какую-то логику описать
Здравствуйте, подскажите пожалуйста как прописать массив для desired_number
Квадратные скобки использовать, в них через запятую элементы. Извлекать элемент через метод shift. И видимо убрать или модифицировать проверку на номер клика по счету.
Простите,а можно для аникейщиков))))😀🙏
А можно подделать результаты если ты участник?
Нет, разве что написать альтернативное приложение, сделать его популярным и себе подкручивать.
Ну вот выдал мне рондом орг цифры, а как экспортировать репостнувших и пронумеровать ?
¯\_(ツ)_/¯
Подскажите можно ли подделать нужное нам число на https://randstuff.ru/number/ Очень надо!!!!
https://greasyfork.org/en/scripts/374750-randstuff-ru
Наверное еще работает.
Не получаться установить скрипт. Подскажите плиз
Да вроде все просто, зайти на сайт greasyfork, нажать установить
Здравствуйте как сделать чтобы второй и третий выграл пожалуйста подскажите
Добрый день. Как уличить группу в фальсификации конкурса?
Добрый день, разве что убедить их использовать какой-то сервис, который предоставляет ссылку с результатом проведения.
Т.е. чтобы было не только скриншот/видео, а еще ссылка на результаты.
Что-то вроде https://randompromo.ru/ , но я не знаток этих сервисов, не пользовался ими.
CAN YOU MAKE A SCRIPT TO FAKE THE RESULTS ON LIZAONAIR WEBSITE?
Привет. Можешь дать скрипт для сайта рандомазер.рф?