Издательский дом ООО "Гейм Лэнд"ЖУРНАЛ ХАКЕР #85, ЯНВАРЬ 2006 г.

Капитуляция защитных механизмов

Крис Касперски ака мыщъх

Хакер, номер #085, стр. 085-110-3


Команда «mov eax, offset loc_20004B» в строке 002002F1h загружает в регистр EAX указатель на начало зашифрованного блока, а команда «mov ecx, 2A5h» задает количество обрабатываемых байт, которое тут же делится на четыре (сдвиг на две позиции вправо эквивалентен делению на четыре, так как 2**2 = 4), поскольку расшифровка идет двойными словами. Цикл расшифровки предельно стандартен и тривиален: lodsd/xor eax, 3F5479F1h/stosd/loop (грузим в EAX очередное двойное слово/делаем ему XOR/сохраняем результат/мотаем цикл). Как это может работать?! Любой программист знает, что в Linux'е сегмент кода доступен только на исполнение (чтение), и любая попытка записи приводит к аварийному завершению приложения. На самом деле это отнюдь не ограничение системы, а всего лишь атрибуты кодового сегмента, назначаемые линкером по умолчанию. В данном случае выставлены все три атрибута: чтение/запись/исполнение, о чем информирует нас IDA в первой строке (Segment permissions: Read/Write/Execute). Прими это во внимание при создании собственных защитных механизмов!

Чтобы расшифровать программу, необходимо проксорить блок от 20004Bh до (020004Bh+2A5h) константой 3F5479F1h. Нажимаем <Shift-F2> и в появившемся диалоговом окне вводим следующий скрипт:

IDA-скрипт, автоматически снимающий шифровку

// объявляем переменные (тип auto)

auto a, x;

// мотаем цикл

for (a = 0x20004B; a < (0x20024B+0x2A5);)

{

// берем очередное двойное слово по адресу a

x = Dword(a);

// расшифровываем его

x = x ^ 0x3F5479F1;

// патчим образ загруженного файла (не сам файл)

PatchDword(a,x);

// модифицируем счетчик цикла (IDA не поддерживает a+=4)

a = a + 4;

}

Если скрипт написан без ошибок, то нажатие <Ctrl-Enter> приведет к его выполнению и расшифрует весь код. Кстати говоря, создатель крэкмиса допустил некритическую ошибку и расшифровал на два байта больше положенного, в результате чего угробил начало расшифровщика, к тому моменту уже отработавшее, как первая ступень ракеты, и никак не препятствующее нормальному выполнению программы:

Процедура расшифровки, пожирающая сама себя

LOAD:002002F0 sub_2002F0 proc near ; CODE XREF: start:loc_200046?p

LOAD:002002F0 jmp near ptr 202077E1h ; испорченные команды

LOAD:002002F1 in al,dx

Теперь, когда весь код расшифрован, мы можем продолжить его анализ. Возвращаемся к месту вызова процедуры расшифровщика call sub_2002F0, расположенной по адресу 00200046h.

Внешний вид дизассемблера после распаковки

LOAD:00200046 call sub_2002F0 ; процедура расшифровки

LOAD:0020004B B8 mov eax,20019Eh ; заслать в eax число 20019Eh

LOAD:0020004C 9E 01 sahf ; бессмысленный мусор

LOAD:0020004E 20 and [eax],al

LOAD:0020004F 00 add [ebx+0F4h],bh

Назад на стр. 085-110-2  Содержание  Вперед на стр. 085-110-4