Мануальная терапия Крис Касперски ака мыщъх Спецвыпуск: Хакер, номер #057, стр. 057-080-3 Первые эксперименты Рассмотрим простейшую программу, которая запрашивает пароль и контролирует целостность своего кода. Ключевой фрагмент исходного текста может выглядеть, например, так (полный вариант можно найти на компакт-диске в файле demo.c): Парольная защита с традиционным самоконтролем #define _PSW_ "godown" // оригинальный пароль // начало охранной зоны begin(){ return 0;}endA(); main(int c, char **v) { int CRC=0;char buf[1024];unsigned char *a; // переменная должна быть статической, потому что локальные // переменные инициируются прямо в коде, изменяя его CRC static int _CRC_= -1; // подсчет CRC for(a=(unsigned char*) begin; a<(unsigned char *)endA;a++) CRC = (CRC + *a); // отладочная дверь под служебные нужды if ((c>1) && !strcmp(v[1],"--debug")) printf("%X\n",CRC); // если CRC не совпадают, выйти не прощаясь! // внимание! нельзя выводить никаких ругательств, иначе нас засекут if (CRC ^ _CRC_) return 0; // проверка пароля printf("enter password:"); gets(buf); if (strcmp(buf, _PSW_)) printf("wrong passwod\n"); else printf("password ok\n"); } // конец охранной зоны endA(){ return 0;} Откомпилировав программу своим любимым транслятором (например Microsoft Visual C++), запустим ее с ключом "--debug" и посмотрим, какую контрольную сумму она напишет (в моем случае это 47h). Присвоим это значение переменной _CRC_ и перекомпилируем исходный код. Конечно, оставлять отладочный механизм в теле готовой программы нехорошо, однако в качестве демонстрационного примера такой трюк вполне сойдет. Не будем обращать внимание на то, что оригинальный пароль лежит открытым текстом и кто угодно может подсмотреть его. Сосредоточимся исключительно на механизме самоконтроля. Дизассемблирование защитного механизма сразу же показывает тот заветный условный переход, который рулит всем. Вот он - лежит по адресу 4010B1h (см. скрин). Как видно, он ведет к той ветке кода, которая выводит "password ok", поэтому, если мы заменим jz loc_4010CA на jmp short loc_4010CA, любой пароль будет воспринят как правильный. Для этого необходимо заменить 74 17 (машинный код jz loc_4010CA) на EB 17 (jmp short loc_4010CA). Берем любой hex-редактор, например HTE, создаем копию ломаемого файла (я называл ее demo.crk.exe), загружаем в редактор, нажимаем <F6> (mode), выбираем режим pe/image, давим <F5> (goto), вводим адрес условного перехода (4010B1h), затем нажимаем <F4> (edit) и заменяем "74" на "EB". Клавиша <F2> сохраняет все изменения в файле, а <F10> выводит нас из редактора. Запускаем хакнутую программу и… опс! Она не запускается! Так где там наш старый добрый SoftIce? Загружаем программу в Symbol Loader, даем команду "bpm 4010B1" (установить точку доступа на обращение к ячейке 4010B1h, в которой расположен хакнутый условный переход) и по <Ctrl-D> выходим из отладчика, возвращая управление программе. Отладчик тут же всплывает и, словно волшебная лампа Аладдина, мгновенно переносит нас в штаб-квартиру защитного механизма, контролирующего целостность машинного кода. |