Изменяем запретное Крис Касперски Хакер, номер #090, стр. 090-122-5 Возьмем последовательность байтов "A::::::::::::::::::::::::::::::::::D", контрольная сумма которой известна и равна CRC_OK, модифицируем ее некоторым образом, изменив один или несколько произвольно расположенных байтов (они обозначены символом "x"): "A:::::x::::::::::::::::::::::::::xxx::::x:x:D". После этого контрольная сумма модифицированной последовательности будет CRC_NOT_OK, а это плохо. Подделка CRC начинается с выбора позиции "врезки" 4-х корректирующих байт. С точки зрения алгоритма CRC, их положение непринципиально - оно определяется внутренней структурой модифицируемого блока. Для наглядности разместим корректирующие байты в середине: "A:::::x::::::B_12_3_4_C:::::::xxx:::x:x:D". Остается только рассчитать корректирующие байты _1_2_3_4_ и восстановить (в смысле "подделать") CRC. Будем действовать по шагам. 1) в точке "A" СRC равно начальному значению полинома (для CRC32 с отраженным полиномом EDB88320h - это FFFFFFFFh). В точке "D" оно известно из условия задачи и равно CRC_OK; 2) если участок A-B не пуст — считаем CRC от точки "A" до точки "B", используя обычную процедуру update_CRC32(): update_CRC32(unsigned long crc, unsigned char byte) { return crc32nornal[(unsigned char)crc ^ byte] ^ (crc >> 8); } 3) если участок C-D не пуст — считаем CRC от точки "C" до точки "D", используя инверсную процедуру reverse_crc32(): // (c)Dmitry Tomashpolski reverse_crc32(unsigned long crc, unsigned char byte) { return ((crc<<8) ^ crc32inv[(unsigned char)(crc>>24)] ^ (byte)); } 4) двигаясь в обратном направлении от точки "C" к точке "B", вычисляем элементы CRC-таблицы, преобразующие CRC(C) в CRC(B), и запоминаем индексы этих элементов в массиве i: // (c)Dmitry Tomashpolski k = 4; y = CRC_D; if((i[--k] = sr(crc32dir, y, 0xFF000000ul)) < 0) goto err; t = crc32dir[i[k]]; y = (y ^ t)<<8 | i[k]; if((i[--k] = sr(crc32dir, y, 0xFF000000ul)) < 0) goto err; t = crc32dir[i[k]]; y = (y ^ t)<<8 | i[k]; if((i[--k] = sr(crc32dir, y, 0xFF000000ul)) < 0) goto err; t = crc32dir[i[k]]; y = (y ^ t)<<8 | i[k]; if((i[--k] = sr(crc32dir, y, 0xFF000000ul)) < 0) goto err; t = crc32dir[i[k]]; y = (y ^ t)<<8 | i[k]; 5) двигаясь в прямом направлении от точки "B" к точке "C" по индексам, рассчитанным на шаге 4, вычисляем корректирующие байты _1_2_3_4_, записывания их в массив x. // (c)Dmitry Tomashpolski y = CRC_B; x[k] = (unsigned char) y ^ i[k]; z = crc32f(z, x[k]); k++; y = z; x[k] = (unsigned char) y ^ i[k]; z = crc32f(z, x[k]); k++; y = z; x[k] = (unsigned char) y ^ i[k]; z = crc32f(z, x[k]); k++; y = z; x[k] = (unsigned char) y ^ i[k]; z = crc32f(z, x[k]); k++; Остается только переместить массив x на отрезок B-C, удостовериться, что контрольная сумма блока не изменилась, и бежать в ближайший ларек за свежим пивом. Все необходимые для взлома листинги приводятся ниже. Обрати внимание на копирайт. За исключением первого и третьего из них, мыщъх не имеет к ним никакого отношения! Так что за хвост не дергать и ногами не пинать. От теории к практике Прежде чем разрабатывать собственный взломщик CRC32, попробуем повозиться с уже существующим. Скачаем популярный распознаватель упаковщиков PEiD (www.wasm.ru/baixado.php?mode=tool&id=67), установим набор дополнительных плагинов (www.wasm.ru/baixado.php?mode=tool&id=318), в число которых входит и модуль с FixCRC, названием которое говорит само за себя (в аннотации на WASM'е сказано, что он предназначен для исправления поля CheckSum в PE-заголовке, но это не так!). |