• На проекте открылась регистрация только для продавцов. Для обычных пользователей будет открыта позже. Подробнее.
    P.S. Не надо скидывать ссылки на форумы, где у вас ноль сообщений. Подобные заявки будут отклонятся.

Забава с хешам

ddd

(•̪̀●́)=o/̵͇̿̿/'̿̿ ̿ ̿̿
Команда форума
WebOwner
WebVoice
Взято с хабра.
Автор: NeverWalkAloner

Привет. Я хочу показать вам небольшой фокус. Для начала вам потребуется скачать архив с двумя файлами. Оба имеют одинаковый размер и одну и ту же md5 сумму. Проверьте никакого обмана нет. Md5 хеш обоих равен ecea96a6fea9a1744adcc9802ab7590d. Теперь запустите программу good.exe и вы увидите на экране следующее.
9e63508e.jpg

Попробуйте запустить программу evil.exe.
f127c806.jpg

Что-то пошло не так? Тоже так хотите?

О хешах и коллизиях

На самом деле ничего нового во всем этом нет. В действительности данный эффект достигается за счет методов быстрого поиска коллизий для хеш функции разработанных еще в 2004-2006 годах. Если кто не знает, коллизия это два разных набора данных, имеющих одно и тоже хеш-значение. Так вот, в 2004 году группа китайских исследователей разработала алгоритм, основанный на дифференциальном криптоанализе, позволяющий за относительно небольшое время находить два различных случайных блока данных, размером по 128 байт каждый, имеющих одну и ту же md5 сумму. И хотя алгоритм этот в свое время произвел эффект взорвавшейся бомбы быстродействие его оставляло желать лучшего. Но уже в 2006 году чешский криптограф Властимил Клима предложил для поиска коллизий новый метод, позволяющий найти разную пару случайных 128 байтных блоков с одной md5 суммой на персональном компьютере меньше чем за минуту.

Вы скажите но что нам даст обладание такой парой сообщений, мало того что они маленькие(всего 128 байт), так еще в добавок и случайные, т.е. метод не позволяет для заданного сообщение подобрать другое с идентичным хешем. Однако это открывает огромный простор для различного рода атак на выполняемые файлы. И виной тому служит следующая особенность работы любой хеш функции: Хеш функция по своей природе итеративна. Это означает, что при подсчете хеша сообщение разбивается на блоки, к каждому блоку применяется функция сжатия, зависящая от некоторой переменной, называемой вектор инициализации. Результат этой функции будет являться вектором инициализации для следующего блока. Результат функции после работы с последним блоком и будет окончательным хеш значением нашего сообщения.

Схематично это можно представить следующим образом:
si+1 = f(si, Mi), где si вектор инициализации для i-го блока.
Метод Властимила Клима позволяет для любого заданного значения si подобрать два 128-байтных блока M,M` и N,N` таких, что f(f(s, M), M') = f(f(s, N), N').

Таким образом, с помощью данной методики можно сконструировать два файла с одинаковой md5 суммой, но имеющих различные 128 байт в середине.
M0, M1, ..., Mi-1, Mi, Mi+1, Mi+2, ..., Mn,

M0, M1, ..., Mi-1, Ni, Ni+1, Mi+2, ..., Mn.
Обратите внимание что хеши обоих этих файлов совпадут, т.к. различающиеся блоки Mi, Mi+1 и
Ni, Ni+1 вернут в качестве si+2 одно и тоже значение, т.к. f(f(s, Mi), Mi+1) = f(f(s, Ni), Ni+1), а поскольку все последующие данные идентичны то последующие значения функции сжатия для обоих файлов будут совпадать.

Что это нам дает

Теперь перейдем от вещей абстрактных и отдаленных к вопросу практическому. Предположим, что у нас есть исполняемый файл M0, M1, X, X, …, Mn. Но его основе мы можем создать два разных файла M0, M1, N1, N1, …, Mn и M0, M1, N2, N1,…, Mn(просто меняем блоки X на N1 и N2). Если блоки N1 и N2 – это коллизии то хеш-сумма этих файлов будет совпадать.
Теперь представим, что этот исполняемый файл имеет следующую структуру:
if (X == X) then { good_program } else { evil_program }
Вот собственно и весь секрет данного фокуса.

Как сделать самостоятельно

Теперь немного поговорим о том как это сделать самому.
Шаг первый: пишем программу с двойным дном.
Код:
[COLOR=black]#include <stdafx.h> 
#include<iostream>
#include <[COLOR=#0000ff]string[/COLOR]>
[COLOR=#0000ff]using[/COLOR] [COLOR=#0000ff]namespace[/COLOR] std;
[COLOR=#008000]//переменные str1 и str2 в данном примере являются теми самыми элементами X. [/COLOR]
[COLOR=#0000ff]static[/COLOR] [COLOR=#0000ff]char[/COLOR] *str1=[COLOR=#a31515]"qwertyuioplkjhgfdaszxcvbnmkjhgfdsaqwertyuikjh"\
"gbvfdsazxdcvgbhnjikmjhbgfvcdsazxdcfrewqikolkjnhgfqwertyuioplkjh"\
"gfdaszxcvbnmkjhgfdsaqwertyuikjhgbvfdsazxdcvgbhnjikmjhbgfvcdsa"\
"zxdcfrewqikolkjnhgfq123"[/COLOR];
[COLOR=#0000ff]static[/COLOR] [COLOR=#0000ff]char[/COLOR] *str2=[COLOR=#a31515]"qaswderftgyhujikolpmnbvcxzasxdcfvgbhnjmkijuy"\
"gtfdeswaqscfvgyjqaswderftgyhujikolpmnbvcxzasxdcfvgbhnjmkijuyg"\
"tfdeswaqscfvgyjqaswderftgyhujikolpmnbvcxzasxdcfvgbhnjmkijuygt"\
"fdeswaqscfvgyjqwertyuikja2"[/COLOR];

[COLOR=#0000ff]int[/COLOR] good()
{
  [COLOR=#0000ff]int[/COLOR] a;
  std::cout<<[COLOR=#a31515]"Good, nice programme!"[/COLOR];
  std::cin>>a;
  [COLOR=#0000ff]return[/COLOR] 0;
}
[COLOR=#0000ff]int[/COLOR] bed()
{
  [COLOR=#0000ff]int[/COLOR] a;
  [COLOR=#0000ff]for[/COLOR]([COLOR=#0000ff]int[/COLOR] i=0; i<1000; i++)
  {
  std::cout<<[COLOR=#a31515]"Evil, evil code!"[/COLOR];
  }
  std::cin>>a;
  [COLOR=#0000ff]return[/COLOR] 0;
}
[COLOR=#0000ff]int[/COLOR] _tmain([COLOR=#0000ff]int[/COLOR] argc, _TCHAR* argv[])
{
[COLOR=#008000]//строки s и s2 содержат только блоки с коллизиями без лишних элементов[/COLOR]
  [COLOR=#0000ff]string[/COLOR] s=str1;  
  [COLOR=#0000ff]string[/COLOR] s2=str2;    
  s.erase(0,56);
  s.erase(128,8);
  s2.erase(0,64);
   [COLOR=#0000ff]if[/COLOR] (s==s2) {
  [COLOR=#0000ff]return[/COLOR] good();
 } [COLOR=#0000ff]else[/COLOR] {
  [COLOR=#0000ff]return[/COLOR] bed();
 }
  [COLOR=#0000ff]return[/COLOR] 0;
}[/COLOR]

Особое внимание прошу обратить на переменные str1 и str2. Они служат для того, чтобы их можно было быстро найти в hex-редакторе и заменить нужными данными.
Функция main в зависимости от содержимого переменных s вызывает хорошую или плохую версию программы.

Шаг второй: После компиляции программы нужно будет немного поработать с hex-редактором для того чтобы найти в .exe файле наши строки str1 и str2. Скопируй полученный .exe файл. Пусть копия будет называется «обрезанная версия». Откройте копию в hex-редакторе и найди в ней строки str1 и str2. Удалите все данные идущие после первых 64 байт первой из строк. Последние строки полученного файла будут выглядеть вот таким образом:
030774ca.jpg
. Сохраните данный файл.

Шаг третий: Созданный на втором шаге файл будет служить так называемым префиксом для поиска коллизий. Чтобы найти коллизию с заданным префиксом нужно скачать отсюда программу fastcoll(Спасибо ее автору Marc Stevens). Исходники лежат тут.
Запустите программу с параметром –p. В качестве префикса укажите «обрезанную версию». В результате работы программы будут созданы два файла «обрезанная версия_msg1» и «обрезанная версия_msg2».

Шаг четвертый: создайте еще одну копию вашей программы. Пусть оригинал будет называться good.exe, а копия evil.exe. Откройте файлы msg1 и msg2 в hex редакторе. Сперва замените блок в котором хранится str2 данными из блока str1. Пусть теперь в них будет одинаковая информация. После этого скопируйте из файла msg1 последние 128 байт и вставьте их в ваш good файл так как показано на рисунке.
3774bd6f.jpg

Обратите внимание, отступы должны соответствовать следующим параметрам: первый блок вставляется прямо в том месте где заканчивается файл «обрезанная версия», второй блок располагается в 96 байтах от первого. Важно: блоки вставлять одни и те же. Это будет доброй версией нашей программы. Сохраняем файл good.exe и открываем файл evil.exe. Блоки в файл evil.exe нужно будет вставить в те же места, что и в good.exe, единственное отличие заключается в том, что первый блок мы берем из файла msg2, а второй из файла msg1. Это различие и обеспечит нам невыполнение условия программы if (s==s2) и соответственно запустит злую версию программы.

Шаг пятый: Profit! Сравниваем md5 суммы файлов, наслаждаемся полученым результатом.

Список литературы:
1. Замечательный сайт с описанием данного метода
2. Сайт Властимила Клима
3. Сайт автора программы findcoll
 

DanKey

0x04
WebVoice
Кууул! Отличная штука!
А есть ли похожий метод по подделке содержимого файла для SHA-1?
Идея в "заражении" торрент-раздач битыми кусками - т.е. подбирать вроде бы правильно прохешированные куски, но с левым содержанием и таким образом портить торренты, посылая в сеть подделанные piece-ы.
 

ddd

(•̪̀●́)=o/̵͇̿̿/'̿̿ ̿ ̿̿
Команда форума
WebOwner
WebVoice
Кууул! Отличная штука!
А есть ли похожий метод по подделке содержимого файла для SHA-1?
Идея в "заражении" торрент-раздач битыми кусками - т.е. подбирать вроде бы правильно прохешированные куски, но с левым содержанием и таким образом портить торренты, посылая в сеть подделанные piece-ы.

Такой фигней вроде правообладатели маются с торрентами.

Еще можно на вирустотале и т.п. подставы делать. Хотя там вроде связка хешей используется.
 
Сверху