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

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

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

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


А что если попробовать заменить JNZ на JZ? Тогда программа поедет крышей. Правильный пароль, которого мы все равно не знаем, она будет воспринимать как неправильный, посылая его обратно, а неправильные пароли встретит с дорогой душой. Вся проблема в том, что программа зашифрована, и прежде чем патчить байты, ее необходимо расшифровать. В принципе, это можно сделать и с помощью IDA Pro, но проще будет воспользоваться коммерческим HIEW'ом или бесплатным редактором HTE, который можно скачать с www.sourceforge.net/projects/hte.

Остановим свой выбор на последнем, хотя он, в отличие от HIEW'а, не может редактировать ELF'ы с искаженным заголовком в режиме image (то есть все виртуальные адреса мы должны вычислять самостоятельно), но зато нам не придется платить.

Загружаем файл в редактор (hte tiny-crackme), нажимаем <F6> (mode) или давим пробел, в появившемся диалоговом окне выбираем elf/program header (просмотр программного заголовка, описывающего сегменты) и видим один-единственный сегмент entry 0 (load). Нажимаем <Enter>, чтобы просмотреть его атрибуты и видим, что он начинается с виртуального адреса 200000h, расположенного в файле по смещению 0h. Следовательно, виртуальный адрес 2000Сfh, по которому расположен наш злополучный условный переход, соответствует смещению 0СFh.

Переходим сюда (<F5>, 0CFh, <Enter>) и видим, что здесь находится байт 84h. Сейчас мы должны расшифровать его, исправить и зашифровать опять. Как это сделать? Вообще-то есть много путей, и все они правильные. Самое простое - наложить XOR. Ведь ключ шифрования нам известен - 3F5479F1h. Но вот в чем вопрос: какая именно часть ключа накладывается на данный байт?То есть каким из четырех байтов шифровать? Это нетрудно выяснить математически.

Начало шифроблока располагается по адресу 200004Bh, так? Тогда наш байт совпадает с 2000CFh - 20004Bh % 4 байтом ключа. Чтобы вычислить значение этого выражения, в HTE достаточно войти в Edit->Evaluate и ввести его в калькулятор. Получится ноль. Значит, байт 2000СFh шифруется первым байтом ключа. На x86 платформе он располагается по меньшему адресу, то есть в младших разрядах числа, и в данном случае равен F1h. Не выходя из калькулятора, даем 84h ^ F1h и получаем 75h, что в точности соответствует опкоду инструкции JNZ. Как следует из руководства Intel, инструкции JZ соответствует опкод 74h. Набираем в калькуляторе 74h ^ F1h и получаем 85h. Это и будет зашифрованное значение опкода JZ. Нажимаем <F4> для активации режима редактирования, записываем на место 84h значение 85h и нажимаем <F2>, чтобы сохранить правку на диск.

Как видно, после хака изменился всего один бит и этим битом оказался младший бит числа: 85h (10000101) --> 84h (10000100). Это потому, что сами опкоды 74h (1110100) и 75h (1110101) различаются всего лишь младшим битом, а XOR - это битовая операция! Другими словами, если шифрование производится путем наложения XOR, то чтобы превратить JZ в JNZ (или наоборот) независимо от ключа шифрования, достаточно инвертировать младший бит шифротекста! И не нужно возиться со всеми этими расчетами! Возьми себе этот трюк на заметку. Нам он еще пригодится. Выходим из редактора и с замиранием сердца запускаем timy-crackme. Увы! Он не запускается! То есть запускается, конечно, но отказывается принимать пароль. Почему?

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