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

Изменяем запретное

Крис Касперски

Хакер, номер #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-заголовке, но это не так!).

Назад на стр. 090-122-4  Содержание  Вперед на стр. 090-122-6
Hosted by uCoz