Первая статья в жизни, просьба сильно не пинать.
Итак начнем.
Не знаю как другие, а я начал свое знакомство с ассемблером с написания своего криптора.
Почему именно криптор? Сначала было интересно изучать ассмемблер (в универе его не дали), хотелось понять, смогу ли я сделать что-то подобное. Хотелось видеть
как код реально исполняется на железе (реальные кодеры меня поймут).
Потом я понял, что на этом можно делать неплохие деньги, и при этом не горбатится на чужого дядю, опять же свой график, работа дома и еще куча плюшек.
Первое время было легко, крипт шел на ура, чистка раз в неделю максимум, то есть все довольны.
Потом понеслось-поехало, что ни день так детект от 1-2 ав (обычно нод + бит, сейчас еще и аваст со своей сетью).
Технику поиска детекта оставим на потом. Сейчас нам интересен другой вопрос: "Как облегчить чистку?"
У меня обычно уходит на читску минут 10-15, иногда приходится делать ее 2 раза в день (связано с невозможностью полностью мутировать код антиэмуля).
Итак какие шаги нам предпринять чтобы максимально повысить отдачу от своего криптора.
После многочисленных проб, я понял, что необходимо маскироваться под реальные компиляторы, то есть структура выходного файла должна строго
соответствовать реальным файлам. Мы берем файл от кого-либо компилятора и смотрим как он устроен, импорт, рич, версия линкера, расположение и порядок секций
и еще много чего. Естественно энтропия и ресурсы. Мы делаем так что задектить файл без кучи ложных детктов очень сложно (но можно). Еще одна хитрость в том, что
мы специально оставляем место в декрипторе, которое будут детектить (чтобы легче было чистить, и чтобы ав сильно не ковырялись в файле), у меня это вызов антиэмулятора.
Вот когда я избрал такой подход, чистить стало легче, стало видно на какие параметры ав смотрят особо. Иногда бывает достаточно добавить\изменить пару байт
(речь не о устранении сигнатуры, а о приближении выходного файла, по параметрам, к реальным файлам).
Есть у меня в крипторе даже возможность сделать выходной файл под разные компиляторы (правда сейчас использую гибрид компиляторов).
Разберем параметры, которым ав уделяют особое внимание.
Одним из основных критириев нормального файла является его импорт. Тут 3 основных вопроса:
1. Какие функции можно использовать?
Берете любое стандартое win приложение и выдираете импорт оттуда.
Мой софт как раз так и делает (для того чтобы выходные файлы разнились, достаточно случайным образом удалять несколько функций из полученных), обычно я использую импорт калькулятора.
2. Как корректно вызвать функции?
Функции должны реально вызываться, или нужно сделать так чтобы ав в это поверили. Ибо неиспользуемый импорт это детект.
Начнем с параметров передаваемых функции, я генерю код который их передает (сами параметры случайны), используются все возможные варианты
передачи параметров в стек (с учетом того, какие варианты используются чаще в реальных программах).
Теперь поговорим о вызове, раньше я делал реальные вызовы обернутые в SEH, запихал все функции, которые нашел в заголовочных файлах masm32.
Это давало кучу детектов и нестабильное поведение выходного файла (ведь параметры то случайные, некоторые функции портили стек и программа вылетала),
и время исполнения вырастало и отлаживать файлы
было нереально под защитой (допустим выходной файл падает, нужно найти это место). Такая схема устраивала меня лишь сначала.
Потом я написал код, который выдирает импорт из PE файлов, детекты ушли, но нужно было улучшить стабильность.
Я подумал, а почему бы не тупо не проскакивать вызовы функций? Добавил в генератор импорта безусловный переход, который стоял перед фейковой функцией,
и стабильность стала 100%. Однако такая схема долго не протянула, так так без всякого эмулятора, ав видели что импорт фейковый, то есть функуии реально не вызываются
(случайные параметры
передаваемые в функцию тоже детект дают). После небольших раздумий мне стало ясно, нужно сделать так чтобы без эмуляции кода не было понятно,
вызывается функция или нет. Это я сделал довольно легко, достаточно было изменить переход на условный, в качетсве условия сравнения какой либо переменной
из секции данных. Все законно, все как у реальных файлов, а функции то не вызываются.
Еще были проблемы с базонезависимым кодом, наш код должен работать по любому загруженному адресу, это накладывает некоторые ограничения на код.
Так же хочу отметить, Avira не видит вызовы функций при косвенной адресации (или детектит), только прямые вызовы.
3. Количество вызовов функций?
У меня функции вызвываются как можно чаще, через каждую строку полезного кода. Это дает нескольких преимушеств: размытие кода декриптора для выявления
сигнатур, усложняет реверс программы, делает код похожим на реальный (так как выходной файл больше файла декриптора, соответсвенно и функций он должен
вызвать и больше и чаще), скрываются реальные вызовы функции (точнее затрудняется их поиск).
Итак начнем.
Не знаю как другие, а я начал свое знакомство с ассемблером с написания своего криптора.
Почему именно криптор? Сначала было интересно изучать ассмемблер (в универе его не дали), хотелось понять, смогу ли я сделать что-то подобное. Хотелось видеть
как код реально исполняется на железе (реальные кодеры меня поймут).
Потом я понял, что на этом можно делать неплохие деньги, и при этом не горбатится на чужого дядю, опять же свой график, работа дома и еще куча плюшек.
Первое время было легко, крипт шел на ура, чистка раз в неделю максимум, то есть все довольны.
Потом понеслось-поехало, что ни день так детект от 1-2 ав (обычно нод + бит, сейчас еще и аваст со своей сетью).
Технику поиска детекта оставим на потом. Сейчас нам интересен другой вопрос: "Как облегчить чистку?"
У меня обычно уходит на читску минут 10-15, иногда приходится делать ее 2 раза в день (связано с невозможностью полностью мутировать код антиэмуля).
Итак какие шаги нам предпринять чтобы максимально повысить отдачу от своего криптора.
После многочисленных проб, я понял, что необходимо маскироваться под реальные компиляторы, то есть структура выходного файла должна строго
соответствовать реальным файлам. Мы берем файл от кого-либо компилятора и смотрим как он устроен, импорт, рич, версия линкера, расположение и порядок секций
и еще много чего. Естественно энтропия и ресурсы. Мы делаем так что задектить файл без кучи ложных детктов очень сложно (но можно). Еще одна хитрость в том, что
мы специально оставляем место в декрипторе, которое будут детектить (чтобы легче было чистить, и чтобы ав сильно не ковырялись в файле), у меня это вызов антиэмулятора.
Вот когда я избрал такой подход, чистить стало легче, стало видно на какие параметры ав смотрят особо. Иногда бывает достаточно добавить\изменить пару байт
(речь не о устранении сигнатуры, а о приближении выходного файла, по параметрам, к реальным файлам).
Есть у меня в крипторе даже возможность сделать выходной файл под разные компиляторы (правда сейчас использую гибрид компиляторов).
Разберем параметры, которым ав уделяют особое внимание.
Одним из основных критириев нормального файла является его импорт. Тут 3 основных вопроса:
1. Какие функции можно использовать?
Берете любое стандартое win приложение и выдираете импорт оттуда.
Мой софт как раз так и делает (для того чтобы выходные файлы разнились, достаточно случайным образом удалять несколько функций из полученных), обычно я использую импорт калькулятора.
2. Как корректно вызвать функции?
Функции должны реально вызываться, или нужно сделать так чтобы ав в это поверили. Ибо неиспользуемый импорт это детект.
Начнем с параметров передаваемых функции, я генерю код который их передает (сами параметры случайны), используются все возможные варианты
передачи параметров в стек (с учетом того, какие варианты используются чаще в реальных программах).
Теперь поговорим о вызове, раньше я делал реальные вызовы обернутые в SEH, запихал все функции, которые нашел в заголовочных файлах masm32.
Это давало кучу детектов и нестабильное поведение выходного файла (ведь параметры то случайные, некоторые функции портили стек и программа вылетала),
и время исполнения вырастало и отлаживать файлы
было нереально под защитой (допустим выходной файл падает, нужно найти это место). Такая схема устраивала меня лишь сначала.
Потом я написал код, который выдирает импорт из PE файлов, детекты ушли, но нужно было улучшить стабильность.
Я подумал, а почему бы не тупо не проскакивать вызовы функций? Добавил в генератор импорта безусловный переход, который стоял перед фейковой функцией,
и стабильность стала 100%. Однако такая схема долго не протянула, так так без всякого эмулятора, ав видели что импорт фейковый, то есть функуии реально не вызываются
(случайные параметры
передаваемые в функцию тоже детект дают). После небольших раздумий мне стало ясно, нужно сделать так чтобы без эмуляции кода не было понятно,
вызывается функция или нет. Это я сделал довольно легко, достаточно было изменить переход на условный, в качетсве условия сравнения какой либо переменной
из секции данных. Все законно, все как у реальных файлов, а функции то не вызываются.
Еще были проблемы с базонезависимым кодом, наш код должен работать по любому загруженному адресу, это накладывает некоторые ограничения на код.
Так же хочу отметить, Avira не видит вызовы функций при косвенной адресации (или детектит), только прямые вызовы.
3. Количество вызовов функций?
У меня функции вызвываются как можно чаще, через каждую строку полезного кода. Это дает нескольких преимушеств: размытие кода декриптора для выявления
сигнатур, усложняет реверс программы, делает код похожим на реальный (так как выходной файл больше файла декриптора, соответсвенно и функций он должен
вызвать и больше и чаще), скрываются реальные вызовы функции (точнее затрудняется их поиск).