В свете последних научных разработок в области компьютерных технологий пользователи все чаще замечают присутствие на компьютерах неких непонятных устройств, опознаваемых операционной системой, как HID-девайсы. В частности, это касается всевозможных игровых контроллеров, устройств ввода и манипуляторов, включая мыши, а также современные HID-клавиатуры. Что это за устройства, почему им присвоены такие названия и как справиться с наиболее распространенными проблемами в их работе, далее и разберемся. Но для начала давайте определимся с пониманием основного термина.
Вам будет интересно: Как работает флешка? Устройство и принцип работы флешки
Разобраться с этим термином в общем-то совершенно несложно. Достаточно просто перевести его с английского языка на русский, в итоге получим что-то вроде устройств с человеческим лицом (интерфейсом). Все оборудование, включаемое в это понятие, принято считать таковым, которое призвано максимально просто взаимодействовать с человеком. В категорию такого оборудования в общем случае относят большинство периферийных устройств, предназначенных для управления компьютерными системами на разных уровнях.
Вам будет интересно: Как работает Wi-Fi роутер: описание, назначение и принцип действия
Для их подключения используются либо USB-интерфейсы и соответствующие порты, либо беспроводные модули Wi-Fi и Bluetooth. Последние два, кстати сказать, тоже относят к классу USB HID. С Wi-Fi-модулями все понятно, ведь те же мыши и клавиатуры беспроводными можно назвать весьма условно, поскольку для их подключения к основному компьютерному блоку как раз и нужен тот самый беспроводный переходник, вставляемый в соответствующий USB-порт. С Bluetooth полной ясности нет, поскольку при подключении к тем же ноутбукам со встроенными «синезубыми» модулями порты USB могут не понадобиться вообще.
HID-клавиатура: что это такое?
Теперь несколько слов непосредственно о клавиатурных блоках. Давайте посмотрим, какие есть виды HID-клавиатур. Что это за устройства, нетрудно сообразить, если просто оценить их визуально. Среди них встречаются и стандартные блоки по типу тех, которые используются на стационарных ПК (стандарт PS/2), и уменьшенные по размерам клавиатуры без цифровых панелей по типу тех, что устанавливаются на ноутбуках с диагоналями экрана 13 дюймов и меньше.
Также можно встретить целые мультимедийные системы, игровые усеченные панели, клавиатуры на мягкой подкладке, сворачивающиеся чуть ли не в трубочку, совершенно миниатюрные блоки с 22, 18, 11 или 10 клавишами и т. д. Вообще считается, что теоретически можно создать блок с 256 клавишами (диапазон ввода/вывода 0-255). Но особой популярностью в последнее время пользуются устройства, на которых положения основных кнопок с литерами и символами изменены, что соответствует заводской установке нестандартной раскладки.
STM32 #6. USB — программируем класс — HID устройство, создаем обычную мышку.
Хорошо забытое старое
На самом деле HID атаки известны уже более 10 лет. Еще в 2012 году пентестер проводил тестирование одной крупной компании. У него никак не получалось проникнуть во внутренний контур. Тогда он собрал специальное устройство, выглядящее как флеш карта, но по факту являющейся как-раз такой поддельной «клавиатурой». Изготовив несколько таких «флешек» он подбросил на парковке перед офисом тестируемой компании. В результате он сначала получил доступ на компьютеры охраны, а к вечеру уже смог успешно закрепиться во внутренней сети.
За эти годы про HID атаки уже написано множество статей, но по факту далеко не все админы и безопасники понимают ту опасность, которую могут представлять данные устройства, особенно в сочетании с грамотно построенной социальной инженерией.
И конечно, разработчики средств защиты тоже придумали механизмы защиты от таких атак. Но по факту из раза в раз приходится сталкиваться с ситуациями, когда даже при наличии данные средства защиты не настроены должным образом.
Так что я предлагаю в этой и двух последующих статьях подробно рассмотреть какие аппаратные и программные компоненты необходимы для реализации данных атак. Мы соберем концепт такого устройства и посмотрим какие атаки с его помощью можно реализовать.
Железная основа
Когда мы говорим о каком-либо устройстве, то обычно подразумевается некая аппаратная платформа, на которой все должно работать. В нашем случае это будет микроконтроллер, размещенный на макетной плате. Наверняка многие знакомы с макетными платами Arduino, так вот, мы будем использовать похожие макетные платы Teensy. Также в качестве минималистского во всех смыслах варианта мы воспользуемся платой Digispark, которая с одной стороны не обладает всеми теми ресурсами, что есть у Teensy, но зато имеет меньший форм фактор и имеет меньшую стоимость.
На известной китайской площадке продаются несколько версий платы Teensy. Для большинства прошивок представленных в статьях достаточно будет версии Teensy 2.0, но для общего понимания приведем сравнение имеющихся версий макетной платы:
Помимо представленных в таблице, также есть варианты макетных плат с MicroSD адаптером для подключения соответствующих карт памяти.
Макетная плата имеет меньший размер и более скромные характеристики.
- Память программ (FLASH) — 8КБ, из них около 2КБ занимает загрузчик
- ОЗУ (SRAM) — 512 байт
- Энергонезависимая память (EEPROM) — 512 байт
- Тактовая частота 16МГц/16,5МГц (существуют и другие версии)
Самое читаемое
- Арифметико логическое устройство (АЛУ)
- Страничный механизм в процессорах 386+. Механизм трансляции страниц
- Организация разделов на диске
- Диск Picture CD
- White Book/Super Video CD
- Прямой доступ к памяти, эмуляция ISA DMA (PC/PCI, DDMA)
- Карты PCMCIA: интерфейсы PC Card, CardBus
- Таблица дескрипторов прерываний
- Разъемы процессоров
- Интерфейс Slot A
Купить птичий корм в Новосибирске. Анкер клин купить анкер клин.
Устройства человеко-машинного интерфейса (HID-устройства)
Подробности Родительская категория: USB Категория: Применение шины USB
К классу HID (Human Interface Device) относятся устройства, обеспечивающие интерфейс между человеком и компьютером:
- клавиатура, мышь, шар, другие устройства-указатели, джойстик;
- органы управления на лицевой панели компьютера — кнопки, переключатели, регуляторы и т. п.;
- органы управления, присущие пультам дистанционного управления аудио- и видеотехникой, телефонам, различным игровым симуляторам (рули, педали, штурвалы и т. п.).
Для этих устройств характерен небольшой объем передаваемых данных, возникающих для компьютера спонтанно (асинхронно), и умеренные требования к задержке обслуживания. К данному классу относятся и иные устройства с похожим характером данных (считыватели штрихкода, термометры, вольтметры и т. п.). Подробно данный класс описан в документе Device Class Definition for Human Interface Devices (HID), в 2001 году вышла его версия 1.11. Класс HID допускает работу устройств на любой скорости шины USB.
Деление на подклассы учитывает только необходимость поддержки данного устройства на этапе загрузки. Специальный код протокола выделяет только клавиатуру и мышь — стандартные устройства ввода.
С HID-устройствами хост обменивается сообщениями-рапортами (report), которые могут быть трех типов (Report Type):
- тип 1 — ввод (Input) от устройства;
- тип 2 — вывод (Output) в устройство;
- тип 3 — управление свойствами (Feature).
Если устройство способно обмениваться разнообразными (не по типу, а по назначению) рапортами, то каждый рапорт начинается с байта идентификатора рапорта (Reprt ID). Например, комбинация клавиатуры с указателем может давать как рапорты нажатий клавиш, так и рапорты устройства-указателя.
Интерфейс HID-устройства обеспечивает двунаправленный обмен рапортами между устройством и драйвером. В нем имеется:
- обязательный двунаправленный канал (через EP0) для вывода рапортов и ввода по опросу (полинг);
- обязательный однонаправленный канал асинхронного ввода рапортов по прерываниям (от устройства к его драйверу через точку Interrupt-IN);
- необязательный канал вывода по прерываниям; если у устройства имеется точка Interrupt-OUT, то выводные рапорты передаются по ней.
HID-устройства имеют специальный классовый HID-дескриптор, ссылающийся на дескриптор рапортов и набор физических дескрипторов (указываются тип и длина этих дескрипторов, что позволяет получить их по запросу Get_Descriptor).
Дескриптор рапорта представляет собой сложную структуру, описывающую передаваемые данные: назначение (ввод, вывод или управление свойствами), использование, диапазон допустимых значений, размер… Эта информация нужна драйверу HID-устройств, разбирающему (и собирающему) рапорты. Драйвер содержит модуль Item Parser, разбирающий, какому приложению следует передать тот или иной рапорт. Без должного дескриптора рапорта приложение рапорт ни принять, ни послать не сможет.
Набор физических дескрипторов описывает, какой частью тела человек воздействует на тот или иной орган управления. Эти дескрипторы необязательны и сообщаются не многими устройствами; они вносят дополнительные сложности в описание, хотя позволяют приложениям точнее использовать те или иные органы.
HID-устройства поддерживают все стандартные запросы к устройствам и специфические запросы, приведенные в таблице.
Таблица. Классовые запросы к HID-устройствам
Запрос | bmRequestType | bRequest |
Get_Report | 10100001 | 01 |
Get_Idle | 10100001 | 02 |
Get_Protocol | 10100001 | 03 |
Set_Report | 00100001 | 09 |
Set_Idle | 00100001 | 0A |
Set_Protocol | 00100001 | 0B |
Запросы Get_Report и Set_Report служат для приема и передачи рапортов через EP0. Здесь в поле wValue старший байт задает тип рапорта, младший — его идентификатор. В поле wIndex задается номер интерфейса, поле wLength задает длину рапорта, который передается в фазе данных.
Запрос Set_Idle позволяет управлять подачей рапортов по каналу прерываний в случае отсутствия изменений состояния рапортуемых величин. Здесь в поле wValue старший байт задает длительность молчания в покое (idle duration), младший — идентификатор рапорта. В поле wIndex задается номер интерфейса, поле wLength = 0 (фаза данных отсутствует). Если задана нулевая длительность, то устройство будет передавать рапорты только в случае изменений состояния (что требуется, например, для клавиатуры). Ненулевое значение трактуется как длительность интервала (в 4-миллисекундных единицах), в течение которого точка Interrupt-IN отвечает на опросы NAK’ами, если нет изменений состояния. Так, например, можно уменьшить поток «пустых» данных опроса устройств-указателей (мыши или джойстика), не теряя быстроты реакции на события (задаваемая длительность и bInterval, задающий частоту опроса точки Interrupt-IN, независимы).
Запрос Get_Idle позволяет считать текущее значение длительности для рапорта, идентификатор которого задан в младшем байте поля wValue. В поле wIndex задается номер интерфейса, поле wLength = 1 (принимается один байт данных).
Запрос Set_Protocol (только для устройств, участвующих в начальной загрузке) позволяет переключать протокол работы устройства. Тип протокола задается в поле wValue: 0 — протокол (упрощенный), используемый при загрузке (Boot Protocol); 1 — нормальный протокол рапортов (Report Protocol). В поле wIndex задается номер интерфейса, поле wLength = 0.
Запрос Get_Protocol позволяет определить текущий протокол. В поле wIndex задается номер интерфейса, поле wLength=1 (принимается один байт данных).
Терминология класса HID и понятия
Информация об устройстве класса HID содержится в его дескрипторах отчета HID. Дескрипторы отчета предоставлены резидентным ядром драйвером устройства и содержат описания каждой части данных, сгенерированных устройством. Ключевой компонент этих дескрипторов отчета является информацией об использовании, определенной в USB Таблицы Использования HID. (Можно загрузить их с http://www .usb.org/developers/hidpage .) Значения использования описывают три основных типа информации об устройстве:
- средства управления — информация о состоянии устройства такой как вклвыкл или позволяет/запрещает
- данные — вся другая информация, передающая между устройством и узлом
- наборы — группы связанных средств управления и данных
Взятый вместе, страница использования и число использования определяют уникальную константу, описывающую определенный тип устройства или часть того устройства. Например, на Универсальной Настольной странице использования (номер страницы 0x01 ), число использования 0x05 число использования и игровой планшет 0x39 переключатель шляпы.
Логически отличные компоненты устройства класса HID, такие как ось X, ось y, набор, или ползунок, вызывают элементами. Информация об элементах устройства класса HID сгруппирована в массивы вложенных словарей. Главный или внешний элемент уровня обычно описывает само устройство. Например, высокоуровневый элемент для игрового планшета включал бы страницу 0x01 использования (универсальный рабочий стол) и использование номер 0x05 (игровой планшет), сопровождаемый массивом других элементов. Для игрового планшета, содержащего и манипулятор и некоторое число кнопок, этот массив содержал бы элемент для манипулятора и элемент для каждой кнопки. В свою очередь, элемент, представляющий манипулятор, вероятно, содержал бы свой собственный массив элементов, каждый представляющий ось.
Каждый словарь элемента содержит cookie элемента (32-разрядное значение раньше ссылалось на тот определенный элемент), страница использования и число использования, тип набора, и возможно другая информация, такая как минимум и максимум элемента (например, ось X могла бы иметь минимум-127 и максимум 127), и имеет ли элемент предпочтительное состояние. Информация об элементе для всех устройств класса HID, в настоящее время присоединяемых к рабочей системе, доступна в Реестре I/O, таким образом, можно проверить, чтобы видеть, имеет ли устройство элементы, Вам нужно перед созданием интерфейса устройства для передачи с ним.
Менеджер по HID
OS X менеджер по HID состоит из трех уровней:
- менеджер по HID клиент API, обеспечивающий определения и функции Ваше приложение, может использовать для работы с устройствами класса HID
- семья HID, обеспечивающая инфраструктуру HID в ядре, такую как базовые классы, отображение памяти пространства пользователя ядра и код организации очередей и синтаксический анализатор HID
- драйверы HID, предоставленные Apple
Как разработчик приложений, Вы будете непосредственно заинтересованы только с первым уровнем, менеджер по HID клиент API, который этот документ просто вызывает менеджера по HID. Можно получить доступ к информации о менеджере по HID от раздела Sample Code> Hardware Human Interface Device .
Переустановка драйвера
Если учесть, что для любого, имеющегося в системе устройства (внешнего или внутреннего) и его корректной работы необходимо специальное управляющее программное обеспечение, называемое драйвером, логично предположить, что проблема может быть именно в нем. Убедиться в этом можно совершенно просто, если вызвать «Диспетчер устройств». Если оборудование с неполадками будет обнаружено, его сразу можно будет увидеть в списке HID-устройств, для которых драйвер не установлен или в его функционировании произошли сбои. Обычно производители поставляют носители с драйверами под свою периферию, так что переустановить драйвер можно самостоятельно.
Но в большинстве случаев это не нужно, поскольку все оборудование класса HID должно распознаваться любой компьютерной системой и без этого.
В этой ситуации лучше всего удалить проблемное устройство целиком и полностью, а затем перезагрузить компьютер. По идее, Windows найдет и установит недостающий драйвер сама.
Управляющее ПО USB-контроллеров
Нередко причина может крыться даже не в самом оборудовании или его драйверах, а в управляющем ПО USB-контроллеров.
В этом случае рекомендуется обновить драйверы всех контроллеров, находящихся в соответствующем разделе все того же «Диспетчера устройств». Для установки самых свежих версий драйверов в обоих случаях можно воспользоваться специальными программами вроде iObit Driver Booster, которые способны находить и устанавливать обновленное программное обеспечение без участия пользователя.
HAL. USB. HID
Сегодня мы познакомимся с новым классом для USB — это Human Interface Device или как в народе говорят HID.
Данный класс отличается тем, что здесь мы посылаем короткие сообщения, у нас особой вероятности в том, что наши данные все дойдут, но в данный момент это не совсем и важно. Как правило скорость настраивается так, что данные все равно доходят. Самое главное, чтобы данные доходили быстро, поэтому такие интерфейсы, такие классы используют при программировании таких устройств, как манипулятор мышь, джойстик. клавиатура и им подобных. HID класс может быть как предопределённым, то есть предназначенным для конкретных существующих типов устройств, так и произвольный (custom). Со вторым типом мы немного поработаем на следующим занятием, а сегодня поработаем с первым классом и попробуем эмулировать манипулятор «мышь».
И чтобы с данным классом немного поподробнее разобраться, мы попробуем его реализовать в нашем контроллере STM32F407VG.
Для этого мы сначала конечно же сделаем проект.
Проект создаём из проекта TEST002. Назовем его USB_DEVICE_HID. Запустим проект в Cube, отключим выходные светодиоды, кнопку оставим
Включим USB_OTG_FS в режим Device_Only.
В USB Device выбираем Human Interface Device Class (HID)
В Clock Configuration выберем следующие делители
В Configuration ничего не трогаем.
Сгенерируем и запустим проект.
Соберем проект и настроим программатор на авторезет.
Подключим файл в main.c
/* USER CODE END Includes */
Добавим переменные туда же
/* USER CODE BEGIN PV */
#define CURSOR_STEP 1
extern USBD_HandleTypeDef hUsbDeviceFS;
Напишем функцию подготовки буфера для передачи в шину
/* USER CODE BEGIN 0 */
static void GetPointerData(uint8_t *pbuf)
static uint8_t cnt = 0; //счетчик циклов
static uint8_t drct = 0; //направление курсора
int8_t x = 0, y = 0 , but = 0;
/* USER CODE END 0 */
В бесконечный цикл добавим код передачи буфера в шину
/* USER CODE BEGIN WHILE */
/* USER CODE END WHILE */
Соберем проект. Прошьем контроллер и посмотрим результат.
Курсор у нас ползает по диагонали вперёд-назад.
Чтобы всё это увидеть, рекомендую посмотреть видеоурок, который откроется, если Вы нажмёте картинку внизу страницы. Также в видеоуроке я даю некоторые пояснения по поводу видов дескрипторов класса HID и много ещё какой информации. Так что милости прошу на канал в YouTube, там вы ещё не то увидите.
Теперь поиграемся с эмуляцией кнопок мыши.
Закомментируем часть кода в функции подготовки буфера и добавим код для эмуляции нажатия левой кнопки мыши
int8_t x = 0, y = 0 , but = 0;
Соберем, прошьем и попробуем нажать кнопку USER .
Заменим единичку на двойку
if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0)==GPIO_PIN_SET) but= 2 ;
Смотреть ВИДЕОУРОК (нажмите на картинку)
Post Views: 5 048
9 комментариев на “ STM Урок 34. HAL. USB. HID ”
Огромное спасибо за Ваши уроки! Я пытаюсь сделать эммулятор мыши на микроконроллере STM32F103RCT6. В качестве отправдяемых репортов служит следующий набор команд: uint8_t USB_Report_Buf[] = 1, 0, 0, 0, // Нажать кнопку
1, 50, 0, 0, // Переместиться влево на 50 пикселей
0, 0, 0, 0, // Отпустить кнопку
0, 50, 0, 0, // Переместиться влево на 50 пикселей
1, 0, 0, 0, // Нажать кнопку
1, 50, 0, 0, // Переместиться влево на 50 пикселей
0, 0, 0, 0, // Отпустить кнопку
0, 206, 0, 0, // Переместиться вправо на 50 пикселей
0, 206, 0, 0, // Переместиться вправо на 50 пикселей
0, 206, 0, 0, // Переместиться вправо на 50 пикселей
0, 0, 2, 0, // Переместиться вниз на 2 пикселя
0, 0, 0, 0>; Отправка его осуществляется в главном цикле программы: /* USER CODE BEGIN WHILE */
while (1)
/* USER CODE END WHILE */ /* USER CODE BEGIN 3 */
HAL_Delay(1000);
pUSB_Report_Buf = // Установить указатель на начало списка коменд
for (uint8_t i = 0; i < sizeof(USB_Report_Buf)/4; i++) < // Цикл по всем командам списка
USBD_HID_SendReport( // Отправка Репорта
pUSB_Report_Buf += 4; // Увеличиваем указатель на 4 (количество байт в Репорте)
HAL_Delay(500);
>
>
/* USER CODE END 3 */ > Но что-то не то происходит с первой командой (перемещает не на 50 пикселей, а меньше). И это стабильно втечение всего времени работы (главного цикла). Если открыть редактор Paint, то на экране должно быть что-то типа: ___________________ ___________________ ___________________ ___________________ Но вместо этого выводит _________ ___________________ _________ ___________________ Подскажите в чем может быть проблема. Спасибо.
Добрый день.
В режиме отладки в файле usb_hid.c
не проходит проверку это условие
if (pdev->dev_state == USBD_STATE_CONFIGURED)
Что может быть не так с конфигурацией?
Изменилось, видимо, что-то в библиотеке, посмотрите пример в репозитории.
Как зайти в репозиторий?
Выяснил следующее.
При включении платы без ST-link (можно просто снять одну ногу питание) пример заработал, в режиме отладки не работает.
Другие программы в режиме отладке работают без проблем.
Какой-то конфликт за USB между платой и ST-link-oм.
Кто знает как это исправить? Если кому лень нажимать кнопку, то можно сделать вот так
//if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0)==GPIO_PIN_SET) but=2;
// else but=0;
if (but == 0 ) but=2;
else but=0;
//but — надо объявить как глобальную переменную.
Если but в ноль не сбрасывать, то ПК будет думать, что Ваш HID-мышка нажала кнопку и держит.
Проверил плату с Stm32f103c8t6 на работу USB, в среде Ардуино IDE.
Вот такой простой пример с клавиатурой заработал сразу же, без перетыкания проводов на SТ-линке. #include
USBHID HID;
HIDKeyboard Keyboard(HID); void setup() HID.begin(HID_KEYBOARD);
Keyboard.begin(); // useful to detect host capslock state and LEDs
pinMode(PC13, OUTPUT);
delay(1000);
>
void loop() digitalWrite(PC13, HIGH); // turn the LED on (HIGH is the voltage level)
delay(1000); // wait for a second
Keyboard.println(«Hello world»);
digitalWrite(PC13, LOW); // turn the LED off by making the voltage LOW
delay(1000); // wait for a second
>
Приветствую!
Не могли бы Вы ( или лучше на Ты? =-) ) конкретно сказать что за нога питания у ST-Link? Имеется в виду программатор или ST-Link на Discovery?
У меня проблема в том, что ни один вариант USB не виден компьютером…
Есть возможность указать какая именно перемычка или что отпаять/закоротить?
Заранее благодарен!
Не совсем понятна смысловая нагрузка вопроса. Желательно поподробнее, где и какая нога отпаялась,
Здравствуйте, подскажите пожалуйстаб а как организовать чтение координат текущего положения указателя (мыши)ю Спасибо!
HID и приложения
Самым большим преимуществом HID является возможность просто подключить к вашему устройству практически любое периферийное устройство, и оно сразу же начнет работать. Но это только половина магии. А как насчет того, чтобы эти аксессуары работали с приложениями?
Вы можете подключить USB-контроллер к своему ПК, и он, как правило, будет управлять игрой должным образом. Даже если контроллер был сделан после игры, он все равно работает. Разработчикам игры не нужно было ничего делать, чтобы это произошло.
Когда вы подключаете HID-устройство, оно сообщает о своих возможностях операционной системе. Операционная система интерпретирует данные и классифицирует устройство. Это позволяет приложениям и играм ориентироваться на классы устройств, а не на конкретные модели.
Это очень важный элемент HID, и мы принимаем его как должное. Игровой контроллер будет работать с вашей библиотекой Steam. Zoom узнает, что нужно включить вашу веб-камеру. Все это происходит с очень небольшой настройкой с вашей стороны.
Типы устройств интерфейса пользователя
Как упоминалось ранее, USB-периферийные устройства являются наиболее распространенными устройствами с интерфейсом пользователя, которые вы увидите, но есть и другие типы.
USB-устройства относятся к классу «USB-HID». Это включает в себя обычные вещи, такие как клавиатуры, мыши, веб-камеры, трекпады и игровые контроллеры. Другие устройства USB-HID включают термометры, аудио инструменты, медицинское оборудование, телефоны и тренажеры.
Другой распространенный тип – Bluetooth-HID. Это тот же протокол USB-HID с небольшими изменениями для Bluetooth. Как и следовало ожидать, сюда входят устройства, аналогичные USB-HID, но они подключаются через Bluetooth. Мышь Bluetooth будет работать независимо от того, подключена ли она к ПК с Windows, Mac или Chromebook.
Устройства интерфейса пользователя – одни из наиболее распространенных устройств, которые мы используем с компьютерами. Мы не очень ценим, насколько легко ими пользоваться. Было время, когда это было не так просто.
HID не только упростил использование компьютеров, но и внес свой вклад в массовый рынок аксессуаров. Существуют тысячи клавиатур, мышей, веб-камер, контроллеров и других продуктов, о несовместимости с которыми вам просто не нужно беспокоиться.
В истории компьютеров было много достижений, но стандарт Human Interface Device имел оглушительный успех.
Программы для Windows, мобильные приложения, игры — ВСЁ БЕСПЛАТНО, в нашем закрытом телеграмм канале — Подписывайтесь:)