2 мая 2017 г.

Выполнение bytecode или shellcode через VirtualAlloc и CreateThread.

Введение

Сейчас хотел бы показать интересный пример запуска нативного байт кода в управляемой куче на языке C#. Для демонстрации будут использованы примеры примитивных shellcode взятых с сайта https://www.exploit-db.com/. На данном ресурсе публикуются боевые exploit для известного программного обеспечения, а сам сайт является аналогом закрытого milw0rm. Перейдя в раздел https://www.exploit-db.com/shellcodes можно найти огромное количество shellcode для различных операционных систем, и при исполнении делающие от простого открытия диалогового окна до запуска backshell для удаленного доступа к машине. Для того, что бы последовательность байт произвела заложенные в нее действия, ее требуется поместить в оперативную память и передать ей управление, иными словами какой то поток должен сделать CALL по адресу памяти. На языках С\С++ вызов делается очень просто, указатель на блок в памяти преобразуется в указатель на метод, чаще всего void(), и делается его вызов ((void (*)())shellcode)(). Если мы те же действия хотим произвести в управляемой куче, то нам запрещено работать с указателями, но при этом никто не запрещает используя WinAPI и Marshaling заставить систему выполнить то, что мы хотим.

Как это будет работать?

Всё легко и просто, для этого нам понадобится всего две WinAPI функции.

  • VirtualAlloc - используя которую, мы разместим байт код в неуправляемой части памяти нашего приложения.
  • CreateThread - которая создаст поток исполнения, у которого в качестве "Точки входа" (стартового адреса исполнения) будет наш размещенный блок с байт кодом.

Практика.

В примере ниже будет продемонстрировано два метода, 
  • RunCmd запускает cmd.exe внутри текущего консольного приложения.
  • RunMessageBox - создает обычный MessageBox с текстом. 

Далее привожу пример моего приложения. ByteCodeExecutor - класс, который непосредственно располагает байты в памяти и создает поток

    internal static class Program
    {
        /// <summary>
        /// Entry point.
        /// </summary>
        /// <param name="args">Arguments.</param>
        private static void Main(string[] args)
        {
            if (IntPtr.Size != 4)
            {
                throw new NotSupportedException("Examples required x86 platform");
            }
 
            RunCmd();
 
            RunMessageBox();
 
            Console.ReadKey();
        }
 
        private static void RunCmd()
        {
            Console.WriteLine("Console application becomes command line");
 
            // https://www.exploit-db.com/exploits/14052/
            var bytes = new []
            {
                0xFC, 0x33, 0xD2, 0xB2, 0x30, 0x64, 0xFF, 0x32, 0x5A, 0x8B,
                0x52, 0x0C, 0x8B, 0x52, 0x14, 0x8B, 0x72, 0x28, 0x33, 0xC9,
                0xB1, 0x18, 0x33, 0xFF, 0x33, 0xC0, 0xAC, 0x3C, 0x61, 0x7C,
                0x02, 0x2C, 0x20, 0xC1, 0xCF, 0x0D, 0x03, 0xF8, 0xE2, 0xF0,
                0x81, 0xFF, 0x5B, 0xBC, 0x4A, 0x6A, 0x8B, 0x5A, 0x10, 0x8B,
                0x12, 0x75, 0xDA, 0x8B, 0x53, 0x3C, 0x03, 0xD3, 0xFF, 0x72,
                0x34, 0x8B, 0x52, 0x78, 0x03, 0xD3, 0x8B, 0x72, 0x20, 0x03,
                0xF3, 0x33, 0xC9, 0x41, 0xAD, 0x03, 0xC3, 0x81, 0x38, 0x47,
                0x65, 0x74, 0x50, 0x75, 0xF4, 0x81, 0x78, 0x04, 0x72, 0x6F,
                0x63, 0x41, 0x75, 0xEB, 0x81, 0x78, 0x08, 0x64, 0x64, 0x72,
                0x65, 0x75, 0xE2, 0x49, 0x8B, 0x72, 0x24, 0x03, 0xF3, 0x66,
                0x8B, 0x0C, 0x4E, 0x8B, 0x72, 0x1C, 0x03, 0xF3, 0x8B, 0x14,
                0x8E, 0x03, 0xD3, 0x52, 0x68, 0x78, 0x65, 0x63, 0x01, 0xFE,
                0x4C, 0x24, 0x03, 0x68, 0x57, 0x69, 0x6E, 0x45, 0x54, 0x53,
                0xFF, 0xD2, 0x68, 0x63, 0x6D, 0x64, 0x01, 0xFE, 0x4C, 0x24,
                0x03, 0x6A, 0x05, 0x33, 0xC9, 0x8D, 0x4C, 0x24, 0x04, 0x51,
                0xFF, 0xD0, 0x68, 0x65, 0x73, 0x73, 0x01, 0x8B, 0xDF, 0xFE,
                0x4C, 0x24, 0x03, 0x68, 0x50, 0x72, 0x6F, 0x63, 0x68, 0x45,
                0x78, 0x69, 0x74, 0x54, 0xFF, 0x74, 0x24, 0x20, 0xFF, 0x54,
                0x24, 0x20, 0x57, 0xFF, 0xD0
            };
 
            ByteCodeExecutor.Execute(bytes);
        }
        

27 апреля 2017 г.

Часть 4. Clickonce приложение. Что умеет утилита ClickOnceUtil4 и не умеет Mage и её аналоги.

Оглавление


В этой статье я постараюсь описать о имеющихся на текущий момент механизмов предотвращения ошибочных ситуаций при сборке ClickOnce приложения путем уведомления пользователя. Подобные уведомления я не видел в других приложениях. Все проверки со ссылками на страницы, где они описаны, есть в разделе справки. 
  • Ошибка, которую может допустить не знающий пользователь - это создать приложение, у которого исполняемый файл настроен на использование манифеста по умолчанию: "Embed manifest with default settings". Данная проблема хорошо описана на странице Error deploying ClickOnce application - Reference in the manifest does not match the identity of the downloaded assembly. Её решения это в свойстве проекта исполняемого файла перейти в раздел Application и в ComboBox с названием "Manifest" требуется выбрать "Create application without a manifest".
    Почему так происходит? Дело все в том, что в манифест с настройками приложения (Не путать с файлом манифеста ClickOnce), зашивается внутрь исполняемого файла. Манифест представляет из себя XML и содержит, в основном, информацию о запуске для ОС. Такую как например обязательный запуск с правами администратора. Visual Studio дополнительно пишет туда имя сборки <AssemblyIdentity />, которая, по каким то причинам, может отличаться от <AssemblyIdentity />, содержащейся в .manifest файле собранного ClickOnce приложения. Тем самым при запуске мы получим ошибку.
    На данный момент у меня идёт прямая проверка на наличие и отсутствие манифеста в файле. Позже можно добавить проверку на соответствие AssemblyIdentity файла .manifest и той, что внутри исполняемого файла.  Самый простой способ понять есть ли вшитый в файл манифест, это отрыть исполняемый файл блокнотом, и в конце которого можно обнаружить эту XML с манифестом.

    Ниже приведен пример сообщения об ошибке, описанной ранее ситуации, перед началом сборки:

25 апреля 2017 г.

Часть 3. Clickonce приложение. Альтератива Mage.exe. ClickOnceUtil4.exe утилита для создания ClickOnce приложений.

 Скачать исходный код:
https://bitbucket.org/sergey_vaulin/clickonceutil/src
Скачать исполняемый файл:
https://drive.google.com/drive/folders/0B8D3_EaMiiaNMmJWUkFXelhJdW8?resourcekey=0-JuuTuhbAOiLxXsruuwo3SQ&usp=sharing

Как и обещал в прошлой статье, здесь я постараюсь написать особенности созданной мной утилиты для создания ClickOnce приложения, описать "набитые шишки", а так же показать, что ClickOnce приложение можно создать в один щелчок и сразу посмотреть результат. Цель проекта - иметь инструмент как mage, но с недостающими "плюшками". Так же прошу не судить строго за ошибки в английским. И вообще это утилита будет полезна тем, кто не использует Visual Studio в качестве среды разработки.

Основные особенности.

  1. Пользовательское приложение должно быть написано под .NET Framework 4.х версию, а для .NET Framework 3.5 надо тестировать.
  2. Весь функционал заключен в один файл.
  3. Корректно работает с .deploy файлами, а так же без проблем делает переименование.
  4. Выводит предварительный результат построения, а так же уведомляет о известных мне ошибках и проблемах.
  5. Умеет в один щелчок чистить папку с кэшем, а так же открывать IE с результатом работы.
  6. Имеет ссылки на часто используемые (с моей точки зрения) статьи.
  7. Имеет возможность менять имя экземпляра вашего приложения. 
  8. При обновлении происходит пере подсчет всех контрольных сумм.
  9. Умеет вычислять DeployUrl приложения, если папка находится в виртуальном каталоге IIS.
  10. При создании заполнено минимальное количество полей, и будут использованы самые (на мой взгляд) популярные настройки. А именно:
    • Обновление перед запуском
    • Приложения можно установить и запускать в оффлайн режиме.
    • Создавать ярлык на рабочем столе
    • Использовать .deploy расширение к файлам приложения

 Сценарии работы. 

Какие сценарии можно выполнять используя это приложение:
  1. Создание ClickOnce приложение с нуля.
  2. Удалить ClickOnce приложение, конвертировать его в исходное приложение. То есть удалить все файлы, которые нужны для ClickOnce и переименовать все файлы, убрав .deploy расширение в случае использования такового.
  3. Обновление текущего приложение, изменения настроек. Либо путем пересчета контрольной суммы (в случае непредумышленной модификации) вернуть приложение в рабочее состояние. Но тут стоит учитывать, что если манифесты приложения нужно подписать, то следует это сделать после обновления.
  4. Возможность подписать приложение существующим ключом, либо в случае необходимости использовать сгенерированный так называемый "Тестовый ключ", аналогичный тому, который создает Visual Studio.
  5. Очистка ClickOnce кэша
Теперь постараюсь продемонстрировать все сценарии поподробнее.

Предварительная подготовка.

Для простоты и наглядности демонстрации я сделал два подготовительных шага:
  1. Создал простое приложение, состоящее из первого исполняемого файла и выводящее место расположения и версию. Сам файл расположил по пути C:\IISRoot\DELME. Само приложение не имеет цифровой подписи (не имеет заполненного PublicKeyToken), что потребовало бы его подписи.

  2.  Затем папку C:\IISRoot\DELME я сделал виртуальным каталогом в IIS, что бы при создании сразу продемонстрировать feature, с заполнением DeploymentUrl, но никто не запрещает самому указать желаемый путь без размещения в public доступе IIS.

Создание приложения с нуля.

Начальная подготовка закончена, теперь запускаем мою утилиту и жмем кнопку выбора каталога "Choose", переходим в папку, содержащую наше приложение и в случае если директория подходит для работы, то кнопка "Select Folder" станет активной.


В диалоге снизу есть описание всех вариантов папок, поэтому нам для создания требуется папка помеченная как "Can be an application". И сразу хочу заметить, что в папку не следует заходить а просто выбирать ее в родительском каталоге. После выбора нам откроется меню действий и настроек: