Здравствуй уважаемый %habrauser%. В данной статье я поделюсь с вами историей о том как я взломал приложение. Взломать сам EXE-шник приложения не получилось, но желаемый результат был получен другим способом. Чтобы сохранить конфиденциальность буду опускать некоторые моменты, сильно обрезать скрины. И так

image

Этот неживой и баснословный мир


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

Начало


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

Первые шаги — экспериментируем


Устанавливаем приложение запускаем его, чтобы посмотреть, что оно из себя представляет.
Открывается такой сплэш экран, и приложение на несколько секунд зависает (данное зависание не спроста).

Открывается сплэш экран, а за ним, через несколько секунд открывается такое окошко:

image

От нас требуется ввести ключ активации, которого у нас естественно нет. Первое что меня насторожило, это то, что окно ввода ключа активации открывается с ощутимой задержкой, как будто приложение подключается куда-то через интернет и разработчик приложения не позаботился об асинхронном подключении к интернету. Чтобы удостовериться в том, что приложение лезет в интернет отключил сетевые подключения на компьютере выдернул ethernet кабель и вновь запустил приложение. Через некоторое время раздумий о бытие человеческой приложение все-таки открыло окно активации, но после ввода туда случайного текста выдало сообщение о том, что нет подключения к интернету.

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

Лезу в папку уставленной программы:

image

Структура:

  1. Arial Narrow.ttf – шрифт

    Кеп
    image
  2. DataSource.data – файл БД в котором все тесты
  3. *************.exe – екзешник приложения
  4. MySql.Data.dll – бесплатная opensource библиотека от MySql

Наличие библиотек MySql.Data.dll в папке с программой навела на мысль о том, что приложение скорее всего написано на языке C#. Ни для кого не секрет то, что не защищенные специальными утилитами приложения написанные на этом языке программирования легче всего поддаются декомпиляции. Обрадованный данным предположением, мой мозг автоматически дал мне сигнал запустить программу IlSpy, которая позволяет декомпилировать приложения написанные на C# и открыть приложение в нем.

В итоге передо мной открылась такая картина

image

Как видно приложение действительно написано на C#, отображается информация о разработчике, используемой версии .NET. После открытия структуры приложения последовало разочарование.

image

Судя по непонятным знакам, пустым функциям, приложение обфусцировано — код нечитаемый. За помощью я обратился к поисковикам и вскорее нашел бесплатную опенсоурс программу de4dot, которая позволяет деобфусцировать обфусцированные приложения написанные на C#.

Попробуем деобфусцировать и получаем такой результат:

image

Судя по сообщению приложение обфусцировано с помощью .NET Reactor, и декомпилировать его не представляется возможным. После долгих поисков метода деобфускации от защиты .Net Reactor найти так и не удалось.

Тогда я, решил попробовать хотя бы открыть файл базы данных DataSource.data, в SQLite.

image

От нас требуется пароль от базы данных.

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

Уважаемый вы здоровы?


Иногда шаг вперед является результатом пинка в зад

Прошло какое-то время. Когда я копался в файлах нашел эту программу и обратил внимание на файл MySql.Data.dll. А что если поменять MySql.Data.dll на модифицированный, чтобы он отображал строку подключения к бд. Для этих целей есть opensource программа — dnSpy. Она позволяет редактировать код .net приложений и библиотек. Загружаем dll файл в программе и находим класс MySqlConnection и редактируем функцию .ctor:

image

Добавим строку:

System.Windows.Forms.MessageBox.Show(connectionString);


image

Нажимаем «Compile», сохраняем файл, заменяем с оригинальным и наконец запускаем приложение.

Выйдет такое окно:

image

По названию сервера cloudapp.net можно сделать вывод, что база данных создана на Azure.
Скачиваем любую бесплатную утилиту подключения к бд, скажем HeidiSQL. После ввода полученных данных подключения открылась БД. А вот и наши ключи активации:

image

У большинства ключей отсутствовали значения полей Name, CardId, Phone. Видимо эти ключи еще не продали. Добавил из себя 16 значный ключ, и зарегистрировал программу. В папке с установленной программой появился файл data.dat и приложение выдало сообщение об успешной регистрации. В таблице с ключами пропал созданный ранее ключ. После недолгих поисков этот ключ я нашел в таблице logs. Там был мой ключ с подробным описанием характеристик моего компьютера таких как модель, процессор, видеокарта и т.д. Эту строку я удалил, чтобы не оставить после себя следов.

Итог


Стоит отдать должное разработчику приложения, он позаботился о защите своего приложения. Он защитил БД, обфусцировал приложение, содержание data.dat файла тоже зашифровано, но о проверке хеша используемой библиотеки он позабыл.

P.S.: Вред организации, взлом приложения не произвел. К тому времени, пока удалось взломать приложение, другу оно уже не было надобным. Активированная копия приложения была только у меня и третьим лицам передано не было. В связи с ненадобностью приложения у себя я тоже её удалил.

Комментарии (46)


  1. XopHeT
    29.01.2018 09:23
    -1

    «декомпилировать его ну удается возможным.»
    Вероятно имелось в виде «декомпилировать его не представляется возможным»


    1. AkshinM Автор
      29.01.2018 09:30

      спасибо, подправил)


  1. vshmidt
    29.01.2018 09:34

    Забавно, давно у Рихтера кажись было написано пару строк по поводу секурности дот нет не на серверах. Так вот секурности предполагалась за счёт недопущения получения сборок. То есть если ты влез на сервер но уже ничего не поможет. В связи с этим вопрос, строгие имена не гарантируют безопасность в случае со статьей. Мне на ум приходит только компиляция приложения в нативный код на клиентской машине и уже в таком виде проверять целостность и ТД. Какие ещё есть способы защиты?


    1. molnij
      29.01.2018 10:43

      В связи с этим вопрос, строгие имена не гарантируют безопасность в случае со статьей.

      Если это вопрос — то нет, не гарантируют, если ваша цель именно сломать приложение. Просто цепочка слегка удлиняется — потребуется перелопатить все сборки через dnSpy.

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


  1. dartraiden
    29.01.2018 09:44

    В интернете гуляет и мод de4dot с поддержкой .NET Reactor 5.0. Возможно, имело смысл попробовать.


    1. AkshinM Автор
      29.01.2018 10:13

      значит плохо искал)


  1. Gradarius
    29.01.2018 10:45

    Спасибо, достаточно интересная статья.

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


  1. martin_wanderer
    29.01.2018 10:47

    А ведь могло не оказаться прав на таблицу аудита…


    1. AkshinM Автор
      29.01.2018 10:58

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


      1. staticlab
        29.01.2018 12:00

        Вполне могли быть отдельные права на таблицы. Другое дело, что даже R/O-доступ к таблице пользователей — весьма серьёзная дыра в безопасности.


  1. berezuev
    29.01.2018 11:22
    +1

    Ну, тут даже взломом сложно назвать… Разрабы сами положили на клиент логин и пароль от базы данных. Такие косяки даже джунам в 2018-м не позволительны.
    Эх… Наберут по объявлению…


    1. nikitasius
      29.01.2018 12:24

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


      Обфускация обсускацией, а язык-то не меняется.


      1. AkshinM Автор
        29.01.2018 13:21

        Обфускация обсускацией, а язык-то не меняется

        язык то не меняется, но код абсолютно не читаемый


      1. MrDaedra
        29.01.2018 13:45

        Обфускаторы ещё и строки шифруют, так что это не всегда возможно.


        1. AkshinM Автор
          29.01.2018 14:48

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


    1. unsafePtr
      29.01.2018 12:44

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


      1. justmara
        29.01.2018 13:05
        +1

        Даже если подключаться к удалённой базе по логину/паролю, выдаваемому конкретному пользователю с адово-параноидально настроенными правами доступа… То всё равно будут дыры типа чтения чужих данных и тому подобное.


        Так что ответ — никак. Делать поверх базы api и отдавать только его.
        Использовать прямой коннект к базе из клиентского приложения можно разве что в доверенной среде. Например, в рамках локальной сети организации, когда авторизация в базе делается по AD-учётке текущего пользователя.


      1. berezuev
        29.01.2018 13:12

        Обязательно должен быть API между клиентом и базой.

        Вообще, по хорошему, база должна быть доступна только под 127.0.0.1 (по дефолту так и есть), либо внутри сети приложения (если мы говорим про масштабирование), т.к. в СУБД тоже могут быть 0-day уязвимости.


        1. Csharper101
          29.01.2018 13:19

          Под API, вы имеете в виду ORM?


          1. berezuev
            29.01.2018 13:27

            Под API я имею в виду API-сервер. Клиент должен отправлять запросы на сервер с авторизацией. Как реализовать сервер — дело каждого. Самое простое — HTTP с oAuth2.

            А уже на сервере запросы к БД можно делать как угодно: ORM, голый SQL, да хоть через handlersocket…


            1. Csharper101
              29.01.2018 13:32

              Веб-приложения также нужно реализовать?


              1. berezuev
                29.01.2018 13:40

                А какая разница, кто у вас клиент — веб-страница, десктопное/мобильное приложение или чайник Xiaomi?


                1. Csharper101
                  29.01.2018 13:48

                  Но у веб-приложений, реализованных на паттерне mvc, контроллер служит в качестве серверной части приложения, зачем ему что-то еще?


                  1. berezuev
                    29.01.2018 15:31

                    Ну, во-первых, контроллер служит не «для серверной части приложения», а для направления данных от пользователя к системе и наоборот. Бизнес-логика, например, описывается в компонентах, а не в контроллерах.

                    Во-вторых, в современных веб-приложениях повсеместно отделяют фронтенд и бэкенд. И общаются они между собой по API-интерфейсу.


                    1. Csharper101
                      29.01.2018 17:15

                      Но они же в mvc итак отделены


                      1. michael_vostrikov
                        29.01.2018 18:19

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


      1. Csharper101
        29.01.2018 13:16

        Да просто засунуть строку подключения в webconfig/appconfig, оттуда их достать нельзя(как я знаю), другого выхода нет


        1. MrDaedra
          29.01.2018 13:49

          По умолчанию app.config превращается в appname.exe.config и легко редактируется блокнотом чем угодно


        1. darkdaskin
          29.01.2018 14:42

          Шифрование строк подключения производится ключом пользователя ОС. Если перенести этот файл на другой компьютер, расшифровать его приложение уже не сможет. Это защита только от удалённого доступа к файлам на серверах, локальный админ может расшифровать конфиги так же, как и зашифровал.


      1. martin_wanderer
        29.01.2018 14:12

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


      1. nikitasius
        01.02.2018 01:32

        Если ну никак нельзя сделать АПИ, то можно просто плотить view по мастер таблице с аккаунтами и давать каждому клиенту доступ к view. Но далее — надо правильно настроить сервер, чтобы клиент не запускал n-n-n-n… запросы, отъедая по 100% от ядер.


  1. Donquih0te
    29.01.2018 12:43

    Интересно


  1. Csharper101
    29.01.2018 12:43

    А что бы ты делал, если данные в БД были зашифрованы, а ключ к расшифровке находится, где-нибудь на сервере(да, странно, но все все-таки)


    1. AkshinM Автор
      29.01.2018 12:43

      наверное уже сдался бы)


  1. namikiri
    29.01.2018 13:24

    Материал весьма интересный, с удовольствием прочитал, порадовало как ларчик просто открывается. Но… Слишком много размазни на скринах. Неаккуратной, неопрятной размазни. Сплешскрин — зачем? Чтобы посмотреть на слова «Version» и «Copyright»? Замазать размер шрифта Arial — спешите видеть, раскрытие личности по размеру файла!
    Для Хабра можно было и постараться.


    1. AkshinM Автор
      29.01.2018 14:46

      Неаккуратной, неопрятной размазни

      следующий раз учту. даже не обраил на это внимания

      раскрытие личности по размеру файла!

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


  1. dmitryredkin
    29.01.2018 14:26

    А без декомпилятора слабо? Ну там как в старые времена: Запустить Иду, найти функцию проверки активации, пропатчить nop-ами и т.д.?


    1. koot
      29.01.2018 14:42

      Да помню эти старые добрые времена


    1. AkshinM Автор
      29.01.2018 14:43

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


    1. iVladislaV
      29.01.2018 14:53

      Сейчас бы .NET в иде патчить.


      1. qw1
        29.01.2018 17:33

        Как ни странно, я это делал, когда нужно было исправить ровно 1 байт, а не пересобирать всю DLL.

        Декомпилировал сборку в dotPeek, разобрал логику, нашёл нужный переход. Нашёл соответствующее место в IL-коде. Однако, по какому смещению находится в файле нужный байтик, ни один инструмент, кроме IDA, мне не подсказал.


    1. keenua
      29.01.2018 15:45

      Не вижу смысла усложнять себе жизнь. Вот когда часть программы, к примеру шифрование, в нативной библиотеке лежит, тогда и IdaPro пригодится.


    1. dartraiden
      29.01.2018 16:15

      Для отладки .NET лучше использовать специализированный отладчик, допустим, ILSpector или dnSpy.


  1. fareloz
    30.01.2018 15:38

    Когда-то тоже пытался взломать программку на c#. Сначала пытался посмотреть алгоритм создания файла для trial лицензии чтобы самому создать файл и получить бесконечный период. Но там был какой-то хитрый алгоритм с ключами шифрования. Потом хотел просто поменять код чтобы лицензия была валидна при любых аргументах. Но программа тянула не локальные dll, а с GAC. В итоге сдался.


  1. KoMePcAHT
    30.01.2018 18:47

    интересно что делает разработчик когда нужно сменить пароль к бд


    1. AkshinM Автор
      30.01.2018 19:00

      судя по тому как сделано приложение, он его вряд ли поменяет