Видим слева в списке функций три функции: start — функция, с которой начинается выполнение программы, DialogFunc — эта функция общается с нами и некоторая функция sub_140001000. Рассмотрим диалоговую функцию. Декомпилируем её Hex Rays-ом.
В глаза бросается ветвление условий, согласно которому, если некоторая функция sub_140001000 вернет TRUE, то появится сообщение, информирующее нас о отлично проделанной работе, иначе неверно. Разберем нашу заветную функцию sub_140001000. Если мы пропустим её через декомпилятор, то увидим, что в качестве аргумента передается указатель всего на одно значение. Вероятно, это значение берется из диалогового окна и является вводимым ключом. Теперь рассмотрим ассемблерный листинг. Имеется первая проверка условия верности введенных данных. Если условие выполняется, то программа исполняется дальше, если не выполняется, то идет возврат из подпрограммы.
Запустим наш crackme под отладчиком. Воспользуемся x64dbg. Поставим breakpoint на нашей первой проверке. В качестве вводимого ключа используем набор цифр 1234567.
Как видно, происходит проверка значения регистра edx и числа 13h (в десятичной системе исчисления это 19). Вероятно, это проверка на количество введенных знаков ключа (у нас их 7 и в регистре edx число 7). Попробуем ввести другое количество символов. Запустим отладчик заново. Введем 9 цифр 123456789.
Похоже, что так оно и есть. Значит наш ключ должен содержать 19 символов. Вводим 19 символов 1234567890123456789 и переходим к следующему этапу проверки.
На этом шаге осуществляется проверка каждого пятого символа ключа на равенство значению 2Dh. Дело в том, что число 2Dh — это шестнадцатиричный код символа "-". Т.е. наш ключ должен иметь вид xxxx-xxxx-xxxx-xxxx. Используем в качестве ключа 1234-5678-9012-3456 и переходим к следующему шагу.
А на следующем шаге происходит проверка символов на числовую принадлежность. Порядок проверки такой: берется символ из ключа (в счет не идут каждый пятый символ ключа) и к его шестнадцатиричному коду прибавляется число -30 и полученный результат сравнивается с числом 9. Если меньше, то на проверку берется следующий символ ключа, если больше, то выводится сообщение, что ключ неверный. Идем дальше.
На этом шаге осуществляется проверка того, чтобы суммы чисел в блоках были равны. На рисунке выше выделен блок кода, который производит подсчет суммы чисел и область стека, куда эти суммы заносятся. Параллельно суммы блоков суммируются между собой и заносятся в регистр r10. Далее идет деление результата в регистре r10 на 4 (shr r10d,2 — сдвиг на 2 разряда равносилен делению на 4) и сравнение значения из регистра r10 с ранее занесенными значениями в стеке. Отлично. Делаем так, чтобы суммы цифр каждого блока ключа были равны (например 1122-0123-2112-0006) и двигаемся дальше на следующий шаг проверки.
Участок кода, выделенный на рисунке выше, проверяет, чтобы расположение символов в каждом последующем блоке ключа не совпадало с предыдущим. В итоге наш ключ имеет вид 1478-7814-1478-7814. Проверяем.
Отличная работа!
Комментарии (23)
RenatSh
25.08.2016 22:45А существует бесплатный или триальный Hex Rays?
dkv
26.08.2016 07:00В целом, ida здесь лишняя. Основная работа сделана через отладчик и его достаточно. Кстати, а что нынче есть подобное hiew, но для x64?
Ghost_nsk
26.08.2016 09:08Если память не изменяет, в 2013 была проблема с отладкой x64, и файлик видимо не спроста был такой. Думаю задача именно в умении реверсить без отладчика.
Itachi261092
30.08.2016 11:29Отличная статья! А может мне кто нибудь подсказать, насколько реально провести реверс-инжиниринг закрытого кода оси на mp4-плеерах cowon? Проблема в том, что родная ось и оболочка просто безобразны. Хотелось бы иметь возможность как то её кастомизировать. но о её коде вообще ничего не известно. через реверс-инжиниринг возможно разобраться в коде и написать свою кастомную версию прошивки?
dkv
30.08.2016 19:42Так это смотря, что за cowon. Во-первых, для части из них есть Рокбокс. Во-вторых, если для вашего плеера плеера нет Рокбокса, то и спрашивать нужно у комьюнити, почему его нет и как запилить. А в целом — берём полный образ прошивки, прогоняем её через binwalk и чешем репу в зависимости от выхлопа в консоли. Если прошивка закриптована, то ищем способы расшифровать либо снять дамп с памяти самого плеера. Учитывая, что там ARM, а не x86, ассмеблер там будет сильно другой и вот я, например, без декомпилятора его не понимаю вообще.
troyanskiy
Круто!
Возможно я покажусь нубом в этом, хотя, так оно и есть, но нельзя ли просто поменять бинарники в местах, где происходит прыжок если условие не выполняется?
Например с je на jne?
JerleShannara
Это можно, но совершенно некрасиво. Ваш вариант — это «патч» от жадности, вышла новая версия — повторяй заново. Вариант автора — это «кейген», вышла новая версия — ничего не надо делать, если алгоритм ключа не сменили. Плюс вдруг далее где-то проверяется целостность кода, какие-то участки проверки не только проверяют ключ и т.д.
saboteur_kiev
Суть в том, что в статье алгоритм проверки ключа был полностью разбран.
А следовательно собеседование пройдет не тот, кто поменял первый je на jmp, а тот, кто смог разобрать все до конца.
starkelec
Всё правильно подмечено. Реверс-инжиниринг тем и отличается от крэкерства, что подразумевает полный разбор алгоритма защиты, а не его банальный обход безусловным переходом.
REU
«Крекерство» это не только смена переходов, а также кейгенинг, снятие навесных защит и многое другое.
troyanskiy
Это мне понятно, что чем детальнее разберешься как работает программа (кейген), тем больше шансов на получение работы в Лаборатории. У меня вопрос был чисто «спортивный» можно ли вообще подменять условия прыжков в бинарниках. И, судя по ответам, таки можно.
Спасибо!