Pull to refresh

Comments 44

Ну есть метод «в лоб» без разбирательств, если алгоритм генерации случайного числа встроен в вирь, я бы смотрел число «1103515245» в теле, или скомпилил функцию генерации и использовал ее в качестве сигнатуры, ибо это то, что требуется вирю в незашифрованном виде (если конечно не применено комбинирование или какая-то обфускация)

Ну а если по уму, то надо смотерть распределение, дающееся таким генератором ПСЧ, и смотреть варианты его взлома (а его точно давным-давно сломали) и на основе их, а так-же учитывая что XOR обратим, думать дальше :-) Как-то так. ИМХО.
Подход неплохой, но. У этого метода равномерное распределение. Если вы RAND_MAX+1 раз вызовете rand(), она вернет вам все числа от 0 до RAND_MAX ровно по одному разу. А указанное Вами число находится в библиотечной функции rand() и в зараженной программе не встретится. Либо будет встречаться в каждой программе, использующей rand(), если тело функций компилятор помещает в исполняемый файл.
Я просто так понял, что код генератора как раз «зашит», т.е. не используется системный, ок, согласен.

Ну вот так, сходу, приходит на ум только сравнение двух закодированных одинаковых файлов (например исходного notepad и завирусованного его-же, либо одинаковых, но по разному завирусованных файлов), либо если только задетектить — хэш суммы, entry-point, сравнение эталонных длин файлов.

А вот чисто алгоритмическое решение сообразить не могу.
Если конечно вирус был заранее известен, то тогда, можно найти в нем какие-либо повторяющиеся байты на определенном расстоянии, к которым можно прицепится для детекта XOR — ибо какой бы «XOR число» не был использован — они так-же будут повторятся, хоть и будут иметь другие значения…

P.S. OMG, чем мы занимаемся в Пятницу :-D
Всё нормально, у многих завтра понедельник… Перенос выходного на 30е декабря. Если вы, конечно, не сам себе начальник :)
Скорее всего код будет выполняться в WIndows и компилироваться в Visual C++. А в этом случае RAND_MAX равен 0x7fff, т.е. из 32 бит DWORD'а «ксориться» будут только 15. По оставшимся старшим 17 битам вполне можно детектировать вирус
В результате туда забредает не абы кто, а конкретный независимый исследователь, стирает все награбленное и оставляет записочку горе-автору. Замечу, что это «неправомерный доступ к компьютерной информации», вот только преступник не побежит писать заявление.

Вот будет весело если побежит: «знать не знаю ни про какие зловреды, пароль от фтп украли и стерли оттуда коммерческую информацию.» IP ваш, вы туда заходили и что-то уничтожали. Уголовка до двух лет, а то и до четырех лет. А если выяснится что вы это сделали по работе, то и до пяти можно.
Будет весело, это правда. Поэтому мы предупреждаем независимых исследователей и советуем так не делать.
А почему не используют p2p технологии для управления вирусами? Ведь при таком использовании нужно будет лишь прописать начальную magnet ссылку и все, управление не получится так просто заблокировать (выключив СС сервера).
Используют, насколько я знаю.
Ботнеты это очень любят.
Но вообще это гораздо более сложный метод чем FTP / POST(GET) / SMTP ибо есть в системе практически все готовое.
А как в таком случае поступают для перехвата и закрытия ботнетов? А то постоянно пишут только про ботнеты, использующие обычные сервера для управления.
А вообще, как по мне, так это довольно интересная тема насчёт принципов работы и выведения из строя вирусов, использующих р2р (I2C, tor наверно же тоже используются?).
UFO just landed and posted this here
А почему не используют обычные алгоритмы шифрования, допустим с некоторой модификацией? Зачем эти примитивные алгоритмы со сдвигами и прочими школьными шалостями?
По-разному: кто-то ленится, кто-то не умеет, кто-то вовсе не знает. Собственно говоря, об этом и статья :) Но в ЛК все равно расшифровано будет все и вся, так что пущай ленятся дальше.
Ещё вопрос скорости и незаметности :) А вообще от подобных поделок не нужно лютое шифрование а нужна лишь социальная инженерия что бы пациент не подумав, и с криками «всё пропало» побежал денежку платить.
Не совсем строгие условия. Я так понимаю, что ключ для srand один, но последовательность числ rand1 и rand2 будет разной? Взять два (?) закриптованых эксземпляра. crypted1[0] xor crypted2[0] = body1[0] xor rand1 xor body2[0] xor rand2 = body1[0] xor body2[0] xor rand1[0] xor rand2[0] =|body1[0] == body2[0]|= 0 xor rand1[0] xor rand2[0] = | xor 0| = rand1[0] xor rand2[0]. таким образом получить rand1[1] xor rand2[1]. Так как не совсем понял про генератор и каким образом он инициализурется, вродебы двух значений должно быть достаточно, чтобы найти seed и раскодировать все.
Так-с. srand(key); — здесь используется ключ, известный в момент шифрации, но неизвестный нам в момент дешифрации. Генератор случайных чисел в C устроен так: вы инициализируете его вызовом srand(seed) (обычно в параметре указывают time, который при однократном вызове очень случаен), после чего на основе seed строятся следующие числа. Восле задания seed последовательность rand всегда одна и та же. Так устроен указанный алгоритм генерации псевдослучайных чисел и многие другие. В процессе анализа файла антивирусным движком у вас есть зашифрованные данные (только в конкретном файле), а ключа нет. Так вот ваша задача — понять, зашифровано там тело вируса или это просто какой-то мусор. На этапе написания детектирования у вас и тело есть, и ключи уже подобраны, и много вариантов зараженных файлов.
Ну так расшифрованное тело же есть. XOR-им им подозрительный кусок файла и получаем чистую последовательность от rand()-а. То есть, может быть получаем. Подставляем получившиеся числа в формулу rand()-а, если все получилось — он, вирус. Если не вышло — значит не он. Это работает потому, что в используемом rand-е почти нет скрытого состояния, там фактически seed и есть очередное случайное число (минус старший бит, так как RAND_MAX=2147483647). Так что зная первое случайное число, можно тривиально вычислить второе (точнее, два возможных вторых), потом третье, и так далее.
Хочу предостеречь насчет «самого популярного в компиляторах алгоритма». Несмотря на то, что линейный конгруэнтный метод генерации случайных чисел сам по себе неплох, константы, взятые в данной конкретной его реализации, выбраны неудачно. Их опубликовал комитет по стандартизации в качестве примера, просто лишь бы чем-нибудь заполнить пропуски. Но многие программисты библиотек не потрудились проверить, какие там должны стоять числа, и бездумно скопировали их их «стандартного примера». В результате сильно страдают статистические свойства получаемых случайных чисел. Подробно об этом написано в книге William H. Press et al «Numerical Recipes».
Чертовски приятно видеть человека, хорошо разбирающегося в вопросе!
Только методы эти почти всегда часто не от защиты от целенаправленного анализа, а от ковыряния школьниками файла в hex-редакторе на предмет ссылок/учеток. Считается, что таким «исследователям» будет лениво запускать сэмпл в виртуалке или в IDA, да и простая защита от всего этого дела также может быть.
Автор, большое спасибо вам за статью. Очень интересно читать о технологиях борьбы с вредоносным ПО. Жду от Вас еще статей на эту тему. Было бы интересно почитать и о других трюках, применяемых в вирусах, а также об уникальных методах борьбы с ними, которые не реализованы в продукции Ваших конкурентов.
Рады бы рассказать об «уникальных методах борьбы, которые не реализованы в продукции конкурентов», но, боимся, после выхода статьи методы перестанут быть уникальными :)
Может все таки стоит? А то порой зальешь файл на вирустотал и становится очень грустно, когда видишь только 2-3 срабатывания.
Тут надо понимать, что на вирустотал происходит только сканирование базами. Современный же антивирус — это многослойная защита, поведенческий анализ и прочие техники и технологии. Поэтому оценивать антивирусы лишь по вирустотал не стоит.
Я это хорошо понимаю. Только все равно мечтаю, что когда-нибудь сифилис будет определяться еще до его запуска. Хоть и знаю, что это глупая наивная мечта.
Фактически так и есть — зловред запускается в виртуальной среде и там анализируется его поведение :) Это одна из занятных фич продуктов ЛК.
Тут недавно была статься про локеры. Почему антивирусы пропускают такое? Сразу же видно ненормальное поведение программы. В крайнем случае можно лишний раз запросить подтверждение.
Хотелось бы иметь антиврус, которые не скачивал ежедневно базы, а просто контролировал кто-что делает на компьютере и все изменения файлов.
Запускается неизвестный процесс, посмотреть какие вызовы Windows API он использует, потом в процессе работы что делает, куда лезет. Неужели это очень сложно?
Я пользуюсь вашим антивирусом уже много лет, но что-то защищенным себя чувствую только процентов на 80.
Вот то же самое. Мне даже не столько антивирус нужен, сколько какой-нибудь watchdog, который будет следить, лезет ли какой-то левый софт к файлам паролей от Firefox, к примеру, какой набор действий выполняет и по ряду критериев решает легитимны ли они. До сих пор стоящего решения не видел.
Пробовал. Очень фанатичная софтина со сложным файрволом, который хрен пойми как работает. Тем более я за роутером — мне в принципе всё равно. Kerio вроде понятный, но он файрвол и я его не пробовал.
Была одна софтина интересная, но уж больно куцые и неудобные настройки у неё были. Тоже watchdog, но туповатый и не могу вспомнить название :)
И правда. Ну тогда пишите хотя бы о неуникальных методах, которые на сегодняшний день повсеместно применяются в антивирусном ПО. Поведенческий анализ — очень интересное направление. В самом деле, неважно, как вирус там себе шифруется, если его можно вычислить по результатам его деятельности, которые так просто не замаскируешь. Кстати говоря, люди обнаруживают на своем компе новые вирусы в основном именно благодаря поведенческому анализу, то есть наблюдению за поведением пораженного компьютера, которое имеет ряд характерных признаков.
В какой то момент возникло стойкое ощущение что, это статья для обучения вирусописателей, а не анализ антивирусного специалиста.
Подобные способы ещё во времена Синклера существовали. Распространённой темой в те годы было переделывание игр с кассеты под диск. Для этого нужно было получить дамп кода игры в незашифрованном виде, а на кассете он зачастую был зашифрован, а распаковывался при помощи загрузчика, написанного в кодах, но интегрированного в BASIC текст заголовка игры. Обычно все эти загрузчики были очень простыми: банальный XOR по всей программе. Часто XOR'ом загрузчик был завёрнут несколько раз последовательно, не знаю зачем: распаковку это никак не затрудняло, отладчик справлялся с задачей без проблем.

Но особенно запомнилась игра TRAP DOOR. Её дамп был зашифрован плавающим двухбайтным XOR ключом (т.е. ключ менялся в процессе расшифровки). Начальное значение самого ключа загрузчик получал путём неких вычислений в реальном времени, используя значения таймера, который инкрементировался с заданной частотой при помощи прерываний независимо от основного кода программы. Таким образом, прогнав этот фрагмент загрузчика через отладчик, было невозможно получить правильное значение ключа. Далее, по мере распаковки, значение ключа изменялось тоже при помощи процедуры таймера.

В итоге, это оказалась единственная игра загрузчик которой мне так и не удалось сломать. :-/ Конечно, я её потом слил через «волшебную кнопку» (дамп памяти по внешнему прерыванию), но это было нечестно. Сам загрузчик мне в итоге так и не поддался.
1. Если бы я писал автоматический анализатор, я бы просто автоматически трассировал бы исследуемый зловред до тех пор, пока он не дойдёт до системного вызова с обращением к искомому URL, тогда можно одолеть любую обфускацию, а не только XOR. Кстати некоторые вирусы делали во времена MS-DOS так же, трасируя прерывания BIOS до тех пор пока не доходили до адресов BIOS, обходя тем самым от антивирусные мониторы.
2. (Лучше напишу здесь, а не личным письмом, т.к. очень много людей делают эту ошибку) Нет такого слова «шифрация», есть «шифрование».
Поправте меня если я не прав, можно сгенерить паблик и приват ключ, и всю инфу сливать на общедоступное место, закодировав приват ключем, на какойнить форум, или свалку, или канал.и только зная приватный ключ можно будет раскодировать нужную инфу. (вроде как без палева)
При шифровании используются последние 8 бит псеводслучайного числа. Переносы при уможнении и сложении идут влево, поэтому достаточно перебрать 256 возможных значений key — от 0 до 255, примерно так:

int main(void)
{
  char *original = strdup("Hello, world!");
  int len = strlen(original);

  // Encrypt
  int key = 232222329;
  srand(key);
  char *encrypted = strdup(original);
  printf("Original:\t");
  for (int i = 0; i < len; i++) {
    int x = rand();
    printf("%02x ", (unsigned)encrypted[i] & 0xff);
    encrypted[i] ^= x;
  }
  printf("\n");
  
  // Decrypt
  for (int j = 0; j < 256; j++) {
    printf("Attempt %d:\t", j);
    srand(j);
    bool success = true;
    for (int i = 0; i < len; i++) {
      int y = rand();
      char d = encrypted[i] ^ y;
      if (d != original[i]) {
        success = false;
      }
      printf("%02x ", (unsigned)d & 0xff);
    }
    if (success) {
      printf(" <-- this one!\n");
      return 0;
    }
    printf("\n");
  }
  return 1;
}
Прозевал в условии слово DWORD, простой перебор не подойдёт. Но можно узнать ключ, поксорив первый DWORD шифра и тела, пробовать расшифровывать этим ключом следующие DWORD-ы шифра и сравнивать результат с телом:

int main(void)
{
  unsigned* original = (unsigned*)strdup("Hello, world!");
  unsigned* encrypted = (unsigned*)strdup((char*)original);
  int len = strlen((char*)original);

  // Encrypt
  int key = 232222329;
  srand(key);
  printf("Encryption:\nOriginal   keystream   encrypted\n");
  for (int i = 0; i < len / sizeof(unsigned); i++) {
    int x = rand();
    encrypted[i] ^= x;
    printf("%08x ^ %d = %08x\n", original[i], x, encrypted[i]);
  }
  printf("\n");
  
  int candidate_key = original[0] ^ encrypted[0];
  printf("Candidate key=%d\n\n", candidate_key);
  srand(candidate_key);
  printf("Decrypting the rest:\nCyphertext keystream   decrypted\n");
  for (int i = 1; i < len / sizeof(unsigned); i++) {
    int x = rand();
    printf("%08x ^ %d = %08x, expected %08x\n", encrypted[i], x, encrypted[i] ^ x, original[i]);
  }
  printf("\n");

  return 1;
}
>>что она рано или поздно попадет на «операционный стол» вирусному аналитику
Самоуверенно как-то, на деле не всегда так. Рано или поздно Zловред может не попасть! Степень сложности Zловреда бывает разной! Для некоторых хватает автоматики, для чуть посложнее уже нужен человек чуть-чуть знающий ассемблер, но есть такие Zловреды, которые требуют достаточно много времени на анализ и выделение времени очень дорогостоящим специалистом из антивирусной компании. Таких Zловредов очень много! Такие файлы приходится ложить в очередь к экспертам и пока у этих экспертов дойдут руки, Zловред может быть уже модернизирован и улучшен.

Самое интересное то, что по ту сторону стоят порою весьма не глупые парни! Они пишут достаточно серьезные решения. У них тоже многое автоматизировано и налажено.

Я к тому что не стоит читателю статьи не следует покупаться на процитированные мною слова из статьи. Вашу голову при работе за компом ни один антивирус не заменит! Цените Ваше время!!! Ваши сэкономленные пару секунд от броска файла в виртуальную машину могут акнутся часами или днями восстановления вашей рабочей среды.
Ну формально Ваше высказывание никак не противоречит цитате =) «Рано или поздно» можно истолковать и как «наверное, в следующей жизни...» А «попадет на стол» != «алгоритм будет восстановлен».
Какой смысл искать ключ расшифровки, если вы имеете не только зашифрованную строку но и саму программу? Если в ней используется xor, я уверен что функция расшифровки тоже там. Если не там, то поверьте, там будет уж точно не xor :)
Если речь идёт о примере в самом конце, то ключ расшифровки нужен для того, чтобы определить, находится ли в памяти упомянутая программа. В памяти она хранится в зашифрованном виде, ключ неизвестен (и хорошо спрятан, лень искать).

Из-за слабости использованного шифрования вместо перебора всех возможных значений ключа (что слишком долго) достаточно перебрать 256 значений. Ещё быстрее зашифровать сигнатуру 256 ключами и искать эти зашифрованные строки алгоритмом Ахо-Корасика, который ищет все строки сразу, в один проход.
Интересно, а каким образом идет анализ заразы на веб-страницах? Я про всевозможные iframe/plugin detect (js). Идет анализ кода или анализ «поведения» браузера? Несколько раз загружал на вирустотал страничку (html), в которой был зловред по мнению Касперского, но остальные антивирусы его не обнаруживали. Я не про jar/payload, а про html/js (детект плагинов, iframe).
Комбинирование

Например, они комбинируют методы. Запишут урл задом наперед, да еще через байт, а потом еще поксорят с переменным ключом. Да, некоторую автоматику это может сбить с толку. По факту же это не мешает успешно детектировать такие файлы. А как только зловреда разберет вирусный аналитик, он добавит в дешифровщик метод Reverse(Unicode(LinearXor(stream))), после этого все старые и новые версии расшифровываются автоматически.

В частности интересует «По факту же это не мешает успешно детектировать такие файлы.» Например просто поксорим, да поменяем местами символы по pos = (pos+1)%groupLength, например группами по 3. Получим вместо ЧЛЛП┼╨╨ какой-нибудь ЛЧЛ╨П┼╨. И как отсюда очевидно достать? Я конечно не спорю, что XOR — это не самый сильный вид шифрования, но мне кажется, для облома автоматической расшифровки его достаточно…
Sign up to leave a comment.