Капитуляция защитных механизмов Крис Касперски ака мыщъх Хакер, номер #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 |