Защитете се от скенер за подписи по методите на 21 век
Съдържанието на статията
Въведение
Носи се слух, че някои програмисти наистина не искат сигнатурният анализ на продуктите от дейността на други програмисти да ровят в тайните места на техните творения. За да ги скрият, те използват crypters, които традиционно са написани на повече или по-малко езици на ниско ниво. Ами ако опитате Seasharp? Все пак 2013 е на двора!
Цялата информация се предоставя само за образователни цели. Авторът и редакцията не носят отговорност за неправомерното му използване!
Първо, нека накратко да освежим теорията. За да направим това, нека да определим с какво имаме работа.
- Native - машинен код, представител на C ++, програма calc.exe.
- .NET е общата среда за изпълнение CLR, представител на C #, програмата е нашият криптор.
- Cryptor е програма за крипто защита, използвана основно за маскиране на софтуер. Осигурява защита срещу обичайните антивирусни методи за търсене на подписи.
- Мъничето е изходен файл, който съдържа защитена програма в криптирана форма и код за нейното дешифриране с последващо стартиране.
Има следните видове криптори:
- Статичен (старт кодът винаги е един и същ);
- Полиморф (кодът за стартиране винаги е различен).
Те могат да бъдат стартирани по два начина:
- Scantime (запис на дешифриран файл на HDD, стартиране);
- Време за изпълнение (дешифрирането и стартирането се извършват в паметта).
Е, теорията беше повторена, посоката беше избрана, да вървим ...
Scantime Crypter
И така, първият по ред е Scantime, който, за да стартира програмата, е принуден първо да я запише на HDD. Стартирайте Visual Studio и отворете проекта от архиваCsharp_ScanTime_Temp.rar. Щракваме два пъти върху Form1.cs и разглеждаме красивия GUI интерфейс на нашата програма (фиг. 1), кодът на манипулатора е достъпен чрез двойно щракване върху контролите.
Ориз. 1. Шикозен дизайн на нашето приложение. Готови да печелите в държавни търгове!
Хакер #176. Анонимност в интернет
Сега нека разгледаме по-отблизо вътрешността на бутона "Крипта". Всичко започва със създаване на екземпляр на класа System.Resources.ResourceWriter("res.resources"), след което с помощта на метода AddResource задаваме името на новия вложен ресурсен файл и незабавно шифроваме изходния файл по указания път с алгоритъма RC4 и ключа RC4KEY, посочен със запетая. След това влиза в действие CodeDom, в който указваме необходимите опции за компилиране чрез CompilerParameters (GenerateExecutable = true, OutputAssembly = "File.exe", ReferencedAssemblies.Add("System.dll"), EmbeddedResources.Add("res.resources"), CompilerOptions += "/t:winexe"). Опциите за изходния файл са посочени в CompilerResults. За да не изхвърляме твърдия си диск, почистваме временните файлове, като изтриваме File.Delete("res.resources") и накрая проверяваме прясно изпечения боен мъниче за грешки с помощта на CodeDom.Compiler.CompilerError. По принцип това е всичко, те взеха файла, криптираха го, записаха го в ресурсите. Помислете за видовете стартиране.
Всемогъщи темп
Нека се уверим, че при отваряне на нашата програма криптираният файл попада в папката %temp% с временни файлове. Отваряме мъничето или по-скоро текстовия файл на източника от архива Csharp_ScanTime_Temp.rar. Хвърляме бърз поглед на кода и разбираме, че като цяло извършваме почти същите (с някои изключения) действия, но в обратен ред. Извикваме ResourceManager, задаваме името на вложения ресурс и използвания алгоритъм за криптиране с ключа RC4KEY.Резултатът от тези действия се съхранява в променливата на байтовия масив b и става същият файл, който защитихме. Остава да го запиша и пусна. За да направим това, ще използваме класа Path.GetTempPath(), който ще върне пътя до временната папка, подходяща за тази машина, към низовата променлива „nameA“ и за удобство веднага ще добавим името на бъдещия файл Your_File.exe, който ни подхожда. Има байтове, пълният път е готов (включително името), да пишем скоро! За да направим това, извикваме метода WriteAllBytes на класа File, като предаваме зададените преди това параметри като аргументи. Последният ред от код ще бъде Process.Start(nameA), който ще стартира нашия процес.
Недостатъкът на този подход е, че антивирусният скенер ще види искане за запис в папката и ще бъде готов да сканира беззащитна програма в момента, в който се появи. По този начин може да стартира всеки собствен или .NET файл.
NTFS потоци
Отворете втория архив под името Csharp_SanTime_NTFS.rar, вижте файла Source. И виждаме почти същата картина, с изключение на това, че размерът на пънчето се е увеличил повече от два пъти. И всичко това, защото там се използват API функции и техният пълен код трябва да присъства в списъка. Нека го разбием стъпка по стъпка:
- Вместо едно пълно име на файл, ние посочваме друго. Това е името на нашия поток, което ще бъде разделено с двоеточие, което в крайна сметка ще даде следния резултат: JustTempFile.tmp:YourFile.exe.
- Записването се извършва с помощта на класа PInvokeWin32API.WriteAlternateStreamBytes(nameA, NTFSName, b), който приема като аргументи пълното име на файла, името на потока и самите байтове за запис.
- Стартиране на Process.Start(), от което не можете да излезете тук, тъй като този метод няма да работи на Windows 7 и по-нови (не съм тествал Vista). Изходпредоставен мощен API, той се извиква от реда StartNTFSProcess.Start(nameA + ":" + NTFSName), където се осъществява достъп до посочения поток.
- Поддържаме втора пауза и изтриваме файла File.Delete(nameA), тази операция е невидима за окото и папката% temp% изглежда недокосната. Процесът работи правилно, но на диска няма нищо.
Runtime Crypter
В предишните два примера криптираното приложение беше записано в ресурсите на изходния файл и се изпълняваше от HDD. Сега ще го поставим в кода на заготовката, като използваме кодиране Base64 и презаписваме Source всеки път, когато се щракне върху бутона „Crypt“. Разгледаните примери са приложими само за .NET приложения. Ето как изглежда:
Също така шифроваме байтовете, но в същото време създаваме друга низова променлива, в която записваме целия Source, и използвайки метода Replace, заместваме предварително дефинираните етикети с нови данни. Коригираме CodeDom.Compiler.CompilerResults и по-нататък без промени. Но сега, когато отваряме нашия мъниче в същия .NET Reflector, няма да намерим вложени ресурси и ще стане по-трудно да извлечем файла. Да преминем към стартирането.
Както мнозина правят
Отворете файла на проекта от архива Csharp_RunTime_Simple.rar, вижте Source.
Този код ще стартира нашето приложение от паметта, заобикаляйки HDD и антивирусния сигнатурен анализ. Нека да тестваме на работеща антивирусна ... уау, не работи! Какъв е проблемът? Хм... проблемът е в паролата или по-точно в това, че се съхранява в отворена форма, достъпна за статичен анализ. И това означава, че стигнахме до най-интересната и ключова точка на статията ...
Как ще постъпим
Отваряме файловия проект от архива Csharp_RunTime_Hard.rar и наблюдаваме големи промени в програмата.
Фиг. 3. Промененинтерфейс - добавена нова функционалностСега можем да променим информацията за асемблирането и най-накрая завършихме писането на кода за иконата. Проблемът е решен, паролата не се вижда в мънича! Хехе.
Ето как изглежда работата на един сложен мъниче: вземаме файл, криптираме го, разделяме го на части, криптираме частите с различни пароли и предаваме някои от тях. Записваме всичко това във файла Source. Когато такъв мъничък бъде стартиран, той ще извърши всички тези операции в обратен ред и почти мигновено, благодарение на многопоточността и хеш сумите за контролиране на правилното декодиране на байтове. Ето как изглежда:
В първия ред получаваме произволна главна парола, след което шифроваме избрания файл с нея, разделяме дължината му на 4 (ако е странно, добавяме един празен байт). Създаваме масив, равен на размера на тази една част, и използвайки Array.Copy() постепенно копираме криптираните байтове в него. Ние изчисляваме MD5 хеша Convert.ToBase64String() и повторно шифроваме тази част с нова парола. След това е готово за записване в мънича.
Разгледахме най-важното нещо в криптора, сега разгледайте кратък откъс от файла мъниче:
В резултат на този код създаваме нова нишка, общо пет от тях. Първите четири извършват дешифрирането на записаните части, за което всеки път, избирайки парола, проверяват получения хеш на низа с правилния. В края на този процес контролът се връща на основната нишка, където някои байтове след това се обръщат от класа Array.Reverse() и се обединяват в Array.Copy(). Това е всичко, байтовете са готови, последният пети поток се използва за стартиране, изпълняващ System.Reflection.Assembly.Load(), както в първия случай (ако мъничето не стартира, криптираме файла отново).
Проверка с VirusTotal
За да тествам нашия криптор, взех стар ReverseSocksBot, написан на .NET, и го качих във VT (изключително завидимост). Резултатът му беше 26/46 (фиг. 4). След това шифровах файла и го качих отново. Показателят се подобри значително и възлиза на 1/46 (фиг. 5), което е много добре!
Фиг. 4. VirusTotal доФиг. 5. VirusTotal следЗаключение
.NET е интересна и бързо развиваща се платформа, практически няма причина да се страхувате от липсата на Framework на целевата машина и в бъдеще ситуацията само ще се подобри. „Силата“ на използвания алгоритъм за криптиране не е най-важното нещо в един криптор, много по-важно (и по-обещаващо) е да се намери нова комбинация от приложението му.