✔Загадка Хешерезады. Разгадываем интересный кракми White Rabbit и качаем скилл реверсинга - «Новости»

Автор статьи выражает благодарность hasherezade, автору crackme (пароль crackme
).
По правилам нам нужно найти ключи и секретный флаг, а не просто поломать механизмы валидации, чтобы crackme думал, что он решен. Из инструментария нам понадобится: IDA, DiE и PuTTY. Начнем с DiE.
Crackme в DiE
Энтропия в норме, файл ничем не упакован. Это вполне ожидаемо: накрывать кракми известными навесными упаковщиками — признак плохого тона. Поставить такую защиту может кто угодно, а ее снятие — это рутина, а не решение загадки. Давай запустим кракми и посмотрим, как он работает, что выводит на экран, как реагирует на ввод неправильного пароля.
Crackme
При загрузке мы видим цветные строчки и забавного кролика. На ввод неправильного пароля программа пишет строчку «Nope!» и закрывается. Загрузим крякмис в дизассемблер IDA и посмотрим на начало программы, строки и структуру кода.
White Rabbit в IDA
Начальный код очень прост, и у нас есть два пути его анализа: поискать перекрестные ссылки на сообщения о вводе пароля (по-крякерски!) или начать его исследовать с самого начала. Давай пойдем по второму пути — в этом конкретном случае так будет интереснее. Кроме того, обратим внимание на структуру кода: распознанных исполняемых инструкций не так много. И нельзя не заметить размер файла — больше шести мегабайт!
Запомним это все и начинаем исследовать код. Видим несколько вызовов и подпрограмму loc_403CDE
.
loc_403CDE:
push
offset aNope
; "Nope!n"
push
0C0h
; wAttributes
call
sub_403990
add
esp, 8
push
3E8h
; dwMilliseconds
call
ds:Sleep
or
eax, 0FFFFFFFFh
retn
[/code]
Судя по всему, этот код выполняется при неверном вводе пароля: выводится сообщение «Nope!» и программа завершается. Давай переименуем эту подпрограмму в
exit_err
, чтобы было понятнее, что это завершение программы после некорректного ввода данных.
Итак, первый вызов — это
call sub_402CC0
. Заходим в него и разбираемся.
Отрисовка строк в консоли
Вызываются функции работы с атрибутами текста в консоли, кроме того, мы видим буфер текста «Wake up, Neo… I have a challenge for…». Очевидно, этот call отвечает за начальный баннер кракми. Переименуем
call sub_402CC0
в call banner
, чтобы нам было легче читать код в дальнейшем.
Движемся дальше по коду. После вызова загрузочного баннера у нас идет
call sub_4034D0
. Заходим в него — беглый осмотр показывает, что это один из уровней крякмиса. Об этом нам говорят следующие строки кода:
push
offset aPassword1 ; "Password#1:n"
...
push
offset aSoFarSoGood ; "So far, so good!n"
Это данные, которые передаются функции вывода на экран. С уверенностью переименовываем
call sub_4034D0
в call level_1
и начинаем исследовать уровень более детально. После стандартного пролога и механизма защиты от переполнения буфера стека мы видим интересный код:
lea
eax, [ebp+nNumberOfBytesToWrite]
push
65h
; hResData (101)
push
eax
; int
mov
[ebp+nNumberOfBytesToWrite], 0
call
sub_403D90
Давай перейдем в
call sub_403D90
и посмотрим, что там. А там находится несложный код работы с ресурсами. Наблюдается обилие вызовов FindResourceA
, LoadResource
, LockResource
, SizeofResource
. Дальше все это завершается кодом выделения памяти и копирования данных:
mov
esi, [ebp+arg_0]
push
4
; flProtect
push
3000h
; flAllocationType
push
eax
; dwSize
push
0
; lpAddress
mov
[esi], eax
call
ds:VirtualAlloc
push
dword ptr [esi] ; size_t
mov
edi, eax
push
ebx
; void *
push
edi
; void *
call
_memmove_0
Становится понятно, что
sub_403D90
читает ресурс нашего кракми и копирует его в выделенный буфер в памяти. Переименуем sub_403D90
в load_res_in_buf
и остановимся на этом подробнее.
Код
push 65h
говорит нам о ресурсе 101
. Давай вернемся в DiE и посмотрим на ресурсы. Для этого жмем кнопочку Resource и в открывшемся окне раскроем список под названием RT_RCDATA
. Видим два ресурса, из которых нас интересует 101.
Источник новости - google.com