В выделенном участке кода содержится алгоритм проверки блоков ключа. Разберем его подробно.
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, то проверка пройдет этот шаг и начнется последний этап проверки:
Этот участок кода осуществляет контроль, чтобы расположение символов в каждом последующем блоке ключа не совпадало с расположением символов в предыдущем блоке. Сгенерируем ключ, согласно сделанным выводам. Попробуем 9870-5781-1872-7503
Отлично!
Комментарии (29)
armature_current
26.08.2016 08:24А насколько правильно такой метод называть reverse-engineering? Это же в чистом виде дизасэмблер с полным раскрытием сущности «черной коробочки»
starkelec
26.08.2016 08:25+6Дизасемблирование — это инструмент. Реверс инжиниринг — область, в которой этот инструмент применяется.
armature_current
26.08.2016 10:55Хм, а как тогда классифицировать метод, который подразумевает анализ входных и выходных данных, когда сущность объекта исследования не раскрывается, то есть по сути он представляется как некий «черный ящик», по поведению которого восстанавливается модель объекта?
Я почему-то именно так представлял реверс-инжиниринг и в программной индустрии, без дампов памяти.AndreyDmitriev
26.08.2016 11:08+1Ну существуют разные подходы. В данном случае это может быть продемонстрированный метод с нахождением и разбором кода проверки серийника, это может быть брутфорс либо с целью нахождения одного серийника, либо угадыванию алгоритма по входным данным, либо банальная модификация исполняемого файла с целью обхода кода проверки. В общем-то все методы так или иначе — реверс ижиниринг, тут скорее просто вопрос терминологии. Конечной целью является выдача сообщения об успешной проверке, ну а кто какой подход применяет — тут уже на усмотрение хакера. Многие считают «неспортивным» использование брутфорса либо модификацию одного байта без разбора сути алгоритма. Но без «дампов памяти» в реверс инжиниринге как правило не обходится. Да взять скажем, анализ протоколов какой-нибудь нестандартной железки — там снимаются дампы и анализируются, потом воспроизводятся самодельной железкой — для меня это вполне себе реверс инжиниринг.
starkelec
26.08.2016 11:14Задачи реверс инжиниринга можно решать и по вашему и по моему. И то и другое — реверсинг. Просто для каждой конкретной задачи выбирается конкретный метод.
em92
26.08.2016 08:28Реверсингом не занимался с 2011. Как отладчик использовал первую версию OllyDbg с плагинами. x64dbg увидел впервые. Что скажете по поводу сравнения? Поддерживает ли x64dbg плагины, скрипты наподобие OllyScript?
starkelec
26.08.2016 08:32На официальном сайте разработчика есть полный список поддерживаемых плагинов. Что касается сравнения, то по удобству x64dbg ни чуть не уступает OllyDBG.
shevmax
26.08.2016 09:27Есть косяки в x64dbg. Главный косяк в том, что если программа выделит участок памяти и что-то запишет, а потом вы попытаетесь открыть этот адрес, то получите ошибку что адрес не валидный. По этому необходимо в ручную открывать вкладку Memory Map
и в контекстном меню выбирать Switch View. И только после этого отладчик начинает видеть этот адрес. Других путей я не нашел.
Еще хуже будет если программа выделит память и туда запишет какой-то код и там будет инструкция int 3, то при её срабатывании отладчик не сможет даже перейти по адресу этого исключения.
Конечно, периодически падает при закрытии, но в целом отличный годный отладчик. для X64 самое оно.LoadRunner
26.08.2016 09:57Так программа ещё в альфе и обновляется часто.
Что примечательно — два дня назад был резкий скачок скачиваний. Интересно, это потому, что автор первую статью разместил в песочнице и много кто именно там её прочитал?shevmax
26.08.2016 12:39А может дело еще в том, что в гугле по запросу ollydbg 64 на второй позиции стоит x64dbg.
LoadRunner
26.08.2016 12:42+1То есть существует программа почти два года, скачивают её 1-2 человека, а потом раз — свыше 2 тысяч. Снапшот от 24 августа 2016 года, а статья из песочницы вышла 25 августа.
И я думаю, на вторую строчку гугла она попала из-за >2 тысяч прямых запросов именно 24-25 августа.
Может, авторы программы где рекламу кинули, конечно же, но всё это очень подозрительно. Всё в одних датах.
pfemidi
26.08.2016 10:12А как у него с сокрытием отладчика от тех программ, которые проверяют его наличие? В частности скрытие от защиты Themida? Имеются в наличии работоспособные плагины типа олевского StrongOD?
rdifb0
26.08.2016 10:32Когда я последний раз пробовал x64dbg я что-то не увидел там статического анализатора. Что-то поменялось в этом плане, иначе уступает?
Temtaime
26.08.2016 09:23+1Зачем Оля, когда есть Ида?
Evengard
26.08.2016 11:48Иду сложно достать официально. Хотя если честно я в восторге от блоков, которые генерит Ида. Почему подобный подход не используется в других дизассемблерах, я не понимаю.
demimurych
26.08.2016 12:29Потому что это два принципиально разных инструмента которые дополняют друг друга.
REU
26.08.2016 13:17Какие у них принципиальные отличия?
demimurych
26.08.2016 13:27IDA это прежде всего инструмент для создания осмысленного листинга кода.
Oly это прежде всего отладчик со всеми вытекающими.
REU
26.08.2016 13:38Ида тоже отлично отлаживает.
demimurych
26.08.2016 14:14Не вполне.
Во первых, встроенный в IDA дебаггер использует MDE в случае windows и mtrace в случае линукс. Подобная реализация становиться бесполезной чуть более чем полностью, когда вы сталкиваетесь с кодом в котором реализованы антиотладочные механизмы. Поскольку предназначена для отладки «дружественного» кода, и никак не ориентирована на работу с кодом препятствующему отладке.
Во вторых, есть много хороших плагинов к IDA которые реализовывали отладку на приличном уровне, НО они работают с эмулятором исполняемого кода, то есть качество процесса отладки напрямую зависит от качества эмулятора, и может только стремиться к качеству (быть таким же) отладки в полноценном отладчике использующим возможности процессора.
Отладчик в IDA это полезный бонус, но никак не исключающий необходимость использования стороннего отладчика. Это как в ламповые ДОС времена использовать turbo debugger вместо soft ice для реверса кода написанного с целью затруднить его анализ.
AndreyDmitriev
26.08.2016 10:57+1В этом примере не хватает какой-нибудь «изюминки», что ли.
Я это к тому, что когда сходу в дизассемблиррованном файле вы видите что-то типа такого:
то это всё равно, что крякми вам выдали практически на блюдечке с голубой каёмочкой.
Любая банальная минимальная обфускация приведёт к тому, что вы вот так вот просто не найдёте место, где производится анализ серийника.
Это может быть даже не обфускация, а, скажем, хмм, нетрадиционное средство разработки.
Ну вот, к примеру, за завтраком я набросал довольно примитивный пример, внешне похожий на тот, что обсуждается:
crackme02_x64.7z (10.339.522 Bytes)
Это x64 приложение, алгоритм проверки там не сложнее, чем в примере касперского, решения имеются (множественные), но попробуйте его крякнуть на досуге.
Рантайм библиотеку я бросил в ту же папку — должно запускаться на голой Win7x64SP1 «из коробки» (я проверил в виртуалке).
Вирусов нет (VirusTotal никто не отменял и я проверил на ложные срабатывания), а исходники вышлю по запросу.starkelec
26.08.2016 11:17+1Спасибо. Я посмотрю.
VioletGiraffe
26.08.2016 15:05+1Заинтригован! Напишите, пожалуйста, аналогичную заметку и по этому упражнению :)
Scf
26.08.2016 12:13+1Вот да, от крякми ожидается какая-то изюминка, делающая поиск решения менее тривиальным. Многопоточность, таймеры, ВМ, использование API с callback-ами, динамический код, редкие инструкции ассемблера. Да хотя бы цикл через add esp, 4; ret
Evengard
26.08.2016 11:50Это не крякми, это скорее кейгенми. Будь это крякми вы бы просто запатчили условный переход, который выдаёт итоговый результат, и все дела.
Fenomen51
Полезно, большими отладчиками 64 бита не умею отлаживать, а Оля не поддерживает, пришлось забросить увлечение. При случае испытаю сею программу. В Лаборатории раньше был бесплатный курс, хотели детей брать, но меня тоже пустили, только у меня знания ассемблера слабоваты для совсем лёгкого ориентирования в коде
Тема брутфорса не однозначна, универсален и не зависит от «прямоты» рук
DrZlodberg
Любопытно, а для брутфорса ещё никто не пробовал использовать нейронную сеть, обученную на валидных ключах?
REU
Есть symbolic execution.
sysmetic
Мне кажется обучение не будет работать, потому что хоть у нас и есть множество известных ключей по словарю, но зашифрованные данные будут каждый раз иметь вид случайного числа (если используются стандартные криптографические алгоритмы), поэтому невозможно оценить насколько мы ошиблись подбирая ключ. То есть проблема в том что невозможно оценить степень ошибки в значении каждого пробного ключа, а стало быть сеть не сможет учиться.