Изменяем запретное Крис Касперски Хакер, номер #090, стр. 090-122-4 В общих чертах идея "взлома" CRC заключается в добавлении к контролируемому блоку нескольких байт, подгоняющих конечную контрольную сумму под прежнее значение. Как легко показать, количество корректирующих равно разрядности контрольной суммы, то есть CRC16 требует двух, CRC32 – четырех, а CR-64 - восьми байт, рассчитанных специальным образом (или полученных методом перебора, см. врезку "Неизвестные алгоритмы и борьба с ними"). Как же их рассчитать? Помимо используемого алгоритма (включая такие интимные подробности, как значение полинома, начальное значение и xor-out), необходимо знать, откуда и докуда защита считает контрольную сумму. Выяснив это, необходимо решить другой, гораздо более щекотливый вопрос: собираемся ли мы внедрять корректирующие байты внутрь контролируемого блока или ограничимся их дописыванием. Если защитный механизм проверяет целостность всего блока, то лучше и проще всего будет дописать, как это подробно описано в руководстве "CRC and how to Reverse it", с приложенными к нему исходными текстами. Однако длина контролируемого блока (в роли которого чаще всего выступает исполняемый файл) в этом случае заметно изменится! К тому же многие защитные механизмы контролируют целостность фиксированного участка, и хоть дописывай байты, хоть не дописывай — защита не обратит на них никакого внимания, и CRC контролируемого блока после его модификации необратимо изменится! Ниже приведен фрагмент исходного кода плагина "CRC" к утилите PEiD, которая как раз и дописывает 4 корректирующих байта к модифицированному файлу. Пользуйся им на здоровье, только не спрашивай, где взял ;). Вот код от RElf'а для нахождения корректирующих байт #include<stdio.h> unsigned long c,c2,p2,pol=0xEDB88320; long n,k; main() { printf("CRC32 Adjuster (c) 2001 by RElf @ HHT/2\n"); printf("Length of data: "); scanf("%ld",&n); printf("Offset to patch: "); scanf("%ld",&k); n = (n-k)<<3; printf("Current CRC32: 0x"); scanf("%x",&c); printf("Desired CRC32: 0x"); scanf("%x",&c2); c ^= c2; p2 = (pol << 1) | 1; while(n--) if(c&0x80000000) c = (c<<1)^p2; else c<<=1; printf("XOR masks:%02X%02X%02X%02X\n",c&0xff,(c>>8)&0xff,(c>>16)&0xff, c>>24); } Методика внедрения байтов внутрь контролируемого блока более перспективна. Если это машинный код (где нужно исправить один условный переход на другой), нам наверняка удастся переписать несколько машинных команд так, чтобы высвободить место для 4-х байт, не говоря уже о том, что компиляторы всюду вставляют NOP'ы для выравнивания. Если же это ключевой файл типа сертификата, что ж… втиснуться туда еще проще (хотя бы оттяпать от своего имени четыре символа, при условии, что там содержится имя). Рассмотрим практический пример подделки CRC32 с little-endian порядком бит в потоке (наименее значимый бит располагается по меньшему адресу, то есть поток движется справа налево). Остальные алгоритмы взламываются аналогичным образом, с поправкой на специфику разрядности и направления потока. |