Я не очень активный автор, ибо не люблю писать о всякой херне. За последние несколько месяцев я выпустил лишь пост про обратную разработку, который посчитал как минимум интересным, как максимум потенциально полезным. Более того, Вомбат для меня остаётся основным сайтом для общения, поэтому и комментариев тут от меня мало.
Тут есть очень много хороших функций, даже несколько уникальных, но одна в текущем виде создаёт гораздо больше проблем, чем решает: анонимные посты. В идеальном мире идея звучит очень хорошо, но разбивается об реальность.
То, что админы якобы не видят авторов постов, я не расцениваю за правду. Это создаёт очень простую возможность заниматься спамом, а то и выкладывать что-нибудь совершенно незаконное, при этом админы в такой схеме не могут вычислить и наказать виновного. На том же Пикабу админы видят авторов таких постов и такой уязвимости нет.
Но есть и другая сторона: обход автобана.
Предупреждение о субъекте Г я написал сразу после того, как обнаружил его на этом сайте. С ним ведётся холодная война на Вомбате, иногда переходящая в активные действия. Сначала он выкладывает просто хрень категории Д и пытается максимально топорно маскироваться, а после поимки или ухода в бан по рейтингу либо ноет, либо просто начинает срать. И нет, просто дураки тоже иногда приходят, но его поведение резко отличается. У меня вообще подозрение, что он либо тролль, жаждущий внимания, либо, что более вероятно, нездоровый инфантил. Но пост не об этом.
Пост о том, что тут он через некоторое время тоже бы уехал в бан, причём ему даже в политику лезть не нужно для этого, хватает просто низкосортных постов уровня десятилетки, но он теперь пишет исключительно анонимно. А рейтинг от анонимных постов не влияет на рейтинг профиля. То есть делать он так может вечно даже если админы действительно видят авторов, ибо формально отсутствуют нарушения правил.
Если подсчитать рейтинг постов, у которых я уверен в его авторстве, то выходит всего +2, а при исключении первых постов - -13, что уже порог горячего/автобан.
Поэтому я предлагаю новый механизм - анонимный рейтинг. Он скрыт от всех кроме владельца и на него влияют исключительно анонимные посты. Работает аналогично обычному рейтингу, но при уходе за порог просто блокируется функция анонимных постов.
В системы самоуправления я не верю, так как истинная демократия невозможна теоретически, поэтому тег "[ИНИЦИАТИВА]" не ставлю. Желающие могут написать специализированный пост или попросить админов добавить тег на этот.
Короткий познавательный пост, основанный на моей больной фантазии. Все совпадения случайны.
Обратился как-то один человек на профильном форуме с вопросом, как запустить (не сказать чтобы старую) игру на Windows 10. Игра (хотя я бы назвал это технодемо) была разработана на легендарном XNA 4.0 (земля пухом) и планировалась к выпуску через Steam Greenlight (и ему земля пухом) еще в далеком 2012, после чего заброшена и убрана со всех магазинов.
Игра была куплена тем человеком еще в тот момент, когда она легально продавалась. А спустя годы она просто перестала подавать признаки жизни. $5 за полную версию уплочены, а поиграть нельзя. Обидно.
Так как типовые решения по типу установки XNA Redistributable не помогли, то был предложен единственно возможный выход из ситуации - отладка через dnSpy.
Внимание: обратная разработка хоть прямо и не запрещена законодательно, но разрешенные случаи весьма ограниченны. В других странах разрешен явный запрет любых манипуляций через лицензию, превращающий это занятие во вполне наказуемое. Не повторяйте дома.
Так как ПО было приобретено легально и оно не работает, то этот теоретический случай допустим в соответствии со статьей 1280 гражданского кодекса.
Демонстрировать буду на бесплатной демоверсии, скачать можно здесь.
dnSpy
Театр начинается с вешалки, а программа на C# с атрибутов сборки. Они нам сейчас не сильно интересны, поэтому пытаемся сразу запускать отладку. С неизвестными программами лучше использовать виртуальную машину, так как может быть встроена какая-нибудь пакость для кулхацкеров, но мне можно и так.
Ошибка. Открываем стек вызовов и ищем место, где произошел провальный запрос в сеть.
А вот и виновник торжества. По сообщению из исключения можно сделать вполне однозначный вывод, что проблемой является скупердяйство и непредусмотрительность автора, который решил перестать платить за домен и хостинг, а вместе с этим случайно (а может и намеренно) сделал запуск игры невозможным без интернета. Так как на сайте заявлено отсутствие DRM, то это явно недосмотр.
Что тут происходит?
Если почитать документацию на XNA, то этот метод предназначен для загрузки контента и вызывается автоматически при запуске игры. Первым делом выполняется инициализация некоторых вещей, после чего открывается файл настроек (options.xml) и начинает последовательно считываться. Как только считываются параметры аккаунта для таблицы рекордов, то происходит отправка логина+пароля на официальный сайт и попытка получить ID. Если сервер возвращает Failure, то открывается диалог входа, который можно пропустить. Если сервер возвращает число, то игра запускается. А вот если сервер недоступен, то вылетает исключение, которое никак не обрабатывается и приводит к молчаливому вылету.
Диалог входа официально можно пропустить.
На этом этапе есть 2 варианта действий:
Вручную отредактировать настройки и убрать пункт об аккаунте. Тогда игра будет всегда запускаться без входа.
Физически убрать запрос на несуществующий сайт.
Нормальные герои всегда идут в обход, так что переходим к написанию небольшого патча. (На самом деле, о первом варианте я додумался не сразу. Более того, полная версия зависает при убирании этого пункта из настроек).
Выделяем строчку с запросом и нажимает "Изменить инструкции IL". Открывается окно с заголовком "Изменение тела метода".
Это - язык MSIL. Он очень прост и сильно напоминает Forth, на самом деле, но новичка может отпугнуть.
Ключевым элементом является стек. Что такое стек я уже когда-то рассказывал. Это некоторое место, на вершину которого можно последовательно добавлять значения (числа, строки и прочие объекты), а так же снимать их в обратном порядке.
Не эти стеки, но суть та же. Можно добавлять сверху новые фишки и снимать с вершины старые.
ldloc.2: Значение локальной переменной под номером 2 (с типом строки)
ldstr: Строку "&p=".
ldloc.3: Значение локальной переменной под номером 3 (тоже строка).
Потом мы вызываем String::Concat(), принимающий в себя 4 строки и соединяющий их вместе. При вызове метода будут сняты 4 верхние строки со стека и добавлена новая строка.
Вызов следующего метода (WebClient::DownloadString()) снимает строку, полученную от String::Concat(), и веб-клиент. В результате должна остаться только 1 строка, возвращенная WebClient::DownloadString().
Следующим этапом мы должны снять эту строку со стека и сохранить её в локальную переменную 1, но этого не произойдет, так как WebClient::DownloadString() всегда будет проваливаться и выбрасывать исключение. Исключение, если его не обработать сразу, будет раз за разом проваливаться глубже по стеку вызовов, пока не достигнет обработчика или дна. Так как никаких обработчиков по пути нет, то исключение достигает дна и приводит к вылету.
Чтобы избежать получения исключения, мы можем убрать всё, что предназначено для запроса в сеть. Примерно вот так:
8 инструкций превратились в 2: загрузка строки с числом (которое может быть любым) и сохранение в локальную переменную под номером 1.
Сохраняем и проверяем результат.
Было.
Стало.
Из декомпилированного кода полностью исчез кусок с запросом. Осталась лишь загрузка константной строки и сравнение с "Failure", которое всегда будет успешным.
Сохраняем модуль и пытаемся запускать опять.
Жопиздан!
С этой задачей успешно справился человек, который не смыслит в программировании вообще ничего. По его словам, он джва года ждал эту игру!
Но не всё так просто. Если попытаться пройти любой уровень, то вылетит то же самое исключение.
Для исправления точно так же выделяем строку и опять редактируем инструкции в теле метода. Но так как отправка статистики нонче ни на что не влияет, то просто удаляем выделенные инструкции без остатка.
А для надежности выделяем WebClient, нажимаем "Анализировать" и смотрим, где еще может ждать нас подлянка.
В Finish.Update() мы ошибку только что исправили, в Game1.LoadContent() исправили в самом начале, а Login.button1_Click(), Program.Main() и Title.Update() нас не интересуют, так как достаточно просто не делать того, что приведет к обращению в сеть (а конкретно: не открывать диалог входа, не указывать никакие аргументы при запуске и не пытаться авторизоваться через главное меню (вроде бы не реализовано)).
Ну, 3,14 здец!)()))
Не, они все покраснели возле дырки, раздражение 😆
Я только спилить хотел!