В продолжение моего предыдущего разбора «Reverse engineering тестового crackme от Лаборатории Касперского». Нашел на просторах интернета ещё один вариант crackme от Лаборатории Касперского. Автор применил брутфорс для его решения. Этот грубый «крякерский» метод нам тут не подойдёт. Нас интересует разбор алгоритма проверки лицензионного ключа. Можно, конечно, сделать огромную выборку правильных ключей и попробовать найти закономерность, но мне кажется, что лучше немного пореверсить. И так начнем. Начало у crackme такое же, как и в предыдущей статье: ключ должен содержать 19 символов, каждый 5-ый символ должен быть "-" и все символы должны быть цифрами. Перейдем к интересному. Используем в качестве пробного ключа 1234-5678-9012-3456.

image


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

000000014000106E | movsx eax,byte ptr ds:[r9] 
0000000140001072 | add al,byte ptr ds:[r9+1]
0000000140001076 | add al,byte ptr ds:[r9+2]
000000014000107A | movsx ecx,byte ptr ds:[r9+3]
000000014000107F | add eax,ecx
0000000140001081 | add eax,ecx
0000000140001083 | add eax,ecx

На этом участке кода выполняется операция суммирования шестнадцатиричных кодов символов блока в таком порядке — складываются первые три символа блока ключа (а точнее — их шестнадцатиричные коды) и к этой сумме три раза прибавляется код последнего символа блока (например, если наш первый блок ключа 1234, то эта сумма будет выглядеть так 31h+32h+33h+34h+34h+34h=132h) и далее это число заносится в аккумулятор (RAX). Далее идет ключевая строка кода:

0000000140001091 | lea ecx,dword ptr ds:[rcx+rax-150]

Эта строка заносит в ECX результат следующей операции: в RCX хранится код последнего символа блока и к этому коду прибавляется значение, хранящееся в RAX, а как мы помним, там хранится результат операции из предыдущего шага. После, из этой суммы вычитается 150h. На нашем примере это будет выглядеть так: 34h+132h-150h=16h. Далее это значение заносится в стек следующей строкой:

0000000140001098 | mov dword ptr ds:[rbx-4],ecx

И такую операцию программа проводит с каждым блоком ключа, параллельно суммируя результаты, заносимых в стек данных, в регистре r10. После того, как все результаты будут занесены в стек и их сумма помещена в регистр r10, программа разделит содержимое регистра r10 на 4 (shr r10d,2) и проверит на равенство каждое занесенное значение в стек с результатом, полученным от деления. Если значения будут равны, то проверка выполняется дальше, если же нет, то программа скажет, что ключ неверный. По результатам данного анализа мы имеем следующее — результаты вычислений, согласно алгоритму по адресу 140001091, по каждому блоку должны быть равны друг другу. Если мы попробуем ключ 1234-1234-1234-1234, то проверка пройдет этот шаг и начнется последний этап проверки:

image

Этот участок кода осуществляет контроль, чтобы расположение символов в каждом последующем блоке ключа не совпадало с расположением символов в предыдущем блоке. Сгенерируем ключ, согласно сделанным выводам. Попробуем 9870-5781-1872-7503

image

image

Отлично!
Поделиться с друзьями
-->

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


  1. Fenomen51
    26.08.2016 04:24

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

    Тема брутфорса не однозначна, универсален и не зависит от «прямоты» рук


    1. DrZlodberg
      26.08.2016 08:47

      Любопытно, а для брутфорса ещё никто не пробовал использовать нейронную сеть, обученную на валидных ключах?


      1. REU
        26.08.2016 11:35

        Есть symbolic execution.


      1. sysmetic
        27.08.2016 10:04

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


  1. armature_current
    26.08.2016 08:24

    А насколько правильно такой метод называть reverse-engineering? Это же в чистом виде дизасэмблер с полным раскрытием сущности «черной коробочки»


    1. starkelec
      26.08.2016 08:25
      +6

      Дизасемблирование — это инструмент. Реверс инжиниринг — область, в которой этот инструмент применяется.


      1. armature_current
        26.08.2016 10:55

        Хм, а как тогда классифицировать метод, который подразумевает анализ входных и выходных данных, когда сущность объекта исследования не раскрывается, то есть по сути он представляется как некий «черный ящик», по поведению которого восстанавливается модель объекта?
        Я почему-то именно так представлял реверс-инжиниринг и в программной индустрии, без дампов памяти.


        1. AndreyDmitriev
          26.08.2016 11:08
          +1

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


        1. starkelec
          26.08.2016 11:14

          Задачи реверс инжиниринга можно решать и по вашему и по моему. И то и другое — реверсинг. Просто для каждой конкретной задачи выбирается конкретный метод.


  1. em92
    26.08.2016 08:28

    Реверсингом не занимался с 2011. Как отладчик использовал первую версию OllyDbg с плагинами. x64dbg увидел впервые. Что скажете по поводу сравнения? Поддерживает ли x64dbg плагины, скрипты наподобие OllyScript?


    1. starkelec
      26.08.2016 08:32

      На официальном сайте разработчика есть полный список поддерживаемых плагинов. Что касается сравнения, то по удобству x64dbg ни чуть не уступает OllyDBG.


      1. shevmax
        26.08.2016 09:27

        Есть косяки в x64dbg. Главный косяк в том, что если программа выделит участок памяти и что-то запишет, а потом вы попытаетесь открыть этот адрес, то получите ошибку что адрес не валидный. По этому необходимо в ручную открывать вкладку Memory Map
        и в контекстном меню выбирать Switch View. И только после этого отладчик начинает видеть этот адрес. Других путей я не нашел.

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

        Конечно, периодически падает при закрытии, но в целом отличный годный отладчик. для X64 самое оно.


        1. LoadRunner
          26.08.2016 09:57

          Так программа ещё в альфе и обновляется часто.
          Что примечательно — два дня назад был резкий скачок скачиваний. Интересно, это потому, что автор первую статью разместил в песочнице и много кто именно там её прочитал?


          1. shevmax
            26.08.2016 12:39

            А может дело еще в том, что в гугле по запросу ollydbg 64 на второй позиции стоит x64dbg.


            1. LoadRunner
              26.08.2016 12:42
              +1

              То есть существует программа почти два года, скачивают её 1-2 человека, а потом раз — свыше 2 тысяч. Снапшот от 24 августа 2016 года, а статья из песочницы вышла 25 августа.
              И я думаю, на вторую строчку гугла она попала из-за >2 тысяч прямых запросов именно 24-25 августа.
              Может, авторы программы где рекламу кинули, конечно же, но всё это очень подозрительно. Всё в одних датах.


      1. pfemidi
        26.08.2016 10:12

        А как у него с сокрытием отладчика от тех программ, которые проверяют его наличие? В частности скрытие от защиты Themida? Имеются в наличии работоспособные плагины типа олевского StrongOD?


      1. rdifb0
        26.08.2016 10:32

        Когда я последний раз пробовал x64dbg я что-то не увидел там статического анализатора. Что-то поменялось в этом плане, иначе уступает?


    1. Temtaime
      26.08.2016 09:23
      +1

      Зачем Оля, когда есть Ида?


      1. Evengard
        26.08.2016 11:48

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


      1. demimurych
        26.08.2016 12:29

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


        1. REU
          26.08.2016 13:17

          Какие у них принципиальные отличия?


          1. demimurych
            26.08.2016 13:27

            IDA это прежде всего инструмент для создания осмысленного листинга кода.
            Oly это прежде всего отладчик со всеми вытекающими.


            1. REU
              26.08.2016 13:38

              Ида тоже отлично отлаживает.


              1. demimurych
                26.08.2016 14:14

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

                Во вторых, есть много хороших плагинов к IDA которые реализовывали отладку на приличном уровне, НО они работают с эмулятором исполняемого кода, то есть качество процесса отладки напрямую зависит от качества эмулятора, и может только стремиться к качеству (быть таким же) отладки в полноценном отладчике использующим возможности процессора.

                Отладчик в IDA это полезный бонус, но никак не исключающий необходимость использования стороннего отладчика. Это как в ламповые ДОС времена использовать turbo debugger вместо soft ice для реверса кода написанного с целью затруднить его анализ.


  1. AndreyDmitriev
    26.08.2016 10:57
    +1

    В этом примере не хватает какой-нибудь «изюминки», что ли.
    Я это к тому, что когда сходу в дизассемблиррованном файле вы видите что-то типа такого:

    то это всё равно, что крякми вам выдали практически на блюдечке с голубой каёмочкой.
    Любая банальная минимальная обфускация приведёт к тому, что вы вот так вот просто не найдёте место, где производится анализ серийника.
    Это может быть даже не обфускация, а, скажем, хмм, нетрадиционное средство разработки.
    Ну вот, к примеру, за завтраком я набросал довольно примитивный пример, внешне похожий на тот, что обсуждается:
    crackme02_x64.7z (10.339.522 Bytes)

    Это x64 приложение, алгоритм проверки там не сложнее, чем в примере касперского, решения имеются (множественные), но попробуйте его крякнуть на досуге.
    Рантайм библиотеку я бросил в ту же папку — должно запускаться на голой Win7x64SP1 «из коробки» (я проверил в виртуалке).
    Вирусов нет (VirusTotal никто не отменял и я проверил на ложные срабатывания), а исходники вышлю по запросу.


    1. starkelec
      26.08.2016 11:17
      +1

      Спасибо. Я посмотрю.


      1. VioletGiraffe
        26.08.2016 15:05
        +1

        Заинтригован! Напишите, пожалуйста, аналогичную заметку и по этому упражнению :)


    1. Scf
      26.08.2016 12:13
      +1

      Вот да, от крякми ожидается какая-то изюминка, делающая поиск решения менее тривиальным. Многопоточность, таймеры, ВМ, использование API с callback-ами, динамический код, редкие инструкции ассемблера. Да хотя бы цикл через add esp, 4; ret


  1. Evengard
    26.08.2016 11:50

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