beep.sys

Тема в разделе "WASM.ASSEMBLER", создана пользователем asm0day01, 8 июн 2021.

  1. asm0day01

    asm0day01 Member

    Публикаций:
    0
    Регистрация:
    7 янв 2020
    Сообщения:
    128
    как программно открыть beep.sys чтобы звук прозвучал...
    --- Сообщение объединено, 8 июн 2021 ---
    или еще рабочий драйвер... ring0 интересует
    --- Сообщение объединено, 8 июн 2021 ---
    Пример рабочего драйвера есть у кого нибудь?
     
  2. FoxB

    FoxB Member

    Публикаций:
    0
    Регистрация:
    10 июл 2003
    Сообщения:
    105
    в сурсах выньхп или 2к3 посмотрите.

     
    omne999666 нравится это.
  3. njeen

    njeen Active Member

    Публикаций:
    0
    Регистрация:
    26 мар 2017
    Сообщения:
    138
    Адрес:
    Ташлинск
    я уже данного автора по названию темы могу опознать .
    Откройте для себя Walter Oney что ли уже книгу с примерами дров. И сорцы wdk - там есть дрова.
     
  4. M0rg0t

    M0rg0t Well-Known Member

    Публикаций:
    0
    Регистрация:
    18 окт 2010
    Сообщения:
    1.574
    asm0day01, так есть же уроки Four-F на этом сайте, как раз там ассемблер и как раз пример с этим самым beep
     
  5. Vicshann

    Vicshann Member

    Публикаций:
    0
    Регистрация:
    22 сен 2020
    Сообщения:
    32
    Пожалуйста, фальшивый бипер:):
    Код (C):
    1.  
    2. static NTSTATUS OpenDevice(PWSTR DevName, HANDLE* hDev)
    3. {
    4. UNICODE_STRING DevPathUS;
    5. OBJECT_ATTRIBUTES attr;
    6. IO_STATUS_BLOCK iost;
    7. UINT Length = 8;
    8. wchar_t DevPath[MAX_PATH] = {'\\','D','e','v','i','c','e','\\'};
    9. for(int idx=0;*DevName;DevName++,Length++)DevPath[Length] = *DevName;
    10. DevPathUS.Buffer = DevPath;
    11. DevPathUS.Length = Length * sizeof(wchar_t);
    12. DevPathUS.MaximumLength = DevPathUS.Length + sizeof(wchar_t);   //RtlInitUnicodeString(&str, L"\\Device\\xxx");
    13.  
    14. attr.Length = sizeof(OBJECT_ATTRIBUTES);
    15. attr.RootDirectory = 0;
    16. attr.ObjectName = &DevPathUS;
    17. attr.Attributes = 0;
    18. attr.SecurityDescriptor = 0;
    19. attr.SecurityQualityOfService = 0;
    20. return NtCreateFile(hDev, GENERIC_READ | GENERIC_WRITE, &attr, &iost, 0, 0, 0, FILE_OPEN, 0, 0, 0);
    21. }
    22. //------------------------------------------------------------------------------------
    23. static HANDLE OpenBeep(void)
    24. {
    25. HANDLE hBeep = NULL;
    26. OpenDevice(L"Beep", &hBeep);
    27. return hBeep;
    28. }
    29. //------------------------------------------------------------------------------------
    30. static NTSTATUS DoBeep(HANDLE hBeep, DWORD Freq, DWORD Duration)
    31. {  
    32. struct {
    33.   ULONG uFrequency;
    34.   ULONG uDuration;
    35. } param;
    36. IO_STATUS_BLOCK iost;
    37. param.uFrequency = Freq;    // short
    38. param.uDuration  = Duration;
    39. return NtDeviceIoControlFile(hBeep, 0, 0, 0, &iost, 0x00010000, &param, sizeof(param), 0, 0);
    40. }
    41. //------------------------------------------------------------------------------------
    42.  
    43. {
    44.   HANDLE hBeep = OpenBeep();
    45.   DoBeep(hBeep, 1000, 1000);
    46. }
    47.  
     
  6. asm0day01

    asm0day01 Member

    Публикаций:
    0
    Регистрация:
    7 янв 2020
    Сообщения:
    128
    в общем тема не закрыта, народ дайте работающий драйвер и обьясните на "пальцах" как это работает именно _рабочее_ что то а не лом
    :)
     
  7. HoShiMin

    HoShiMin Well-Known Member

    Публикаций:
    5
    Регистрация:
    17 дек 2016
    Сообщения:
    1.422
    Адрес:
    Россия, Нижний Новгород
    В системе есть аппаратный программируемый таймер (PIT, Programmable Interval Timer): Programmable Interval Timer - OSDev Wiki
    У этого таймера есть три выхода (канала):
    Channel 0 - идёт на IRQ0, что позволяет периодически генерировать прерывания.
    Channel 1 - в старых системах использовался для регенерации ячеек DRAM, но давно не используется.
    Channel 2 - идёт напрямую на пищалку.

    Этот таймер тикает с фиксированной частотой 1.193182 МГц и может работать в режиме генератора прямоугольных импульсов.
    Режим таймера настраивается путём записи в порт 0x43 следующей битовой маски (я отметил нужное):

    Bits: Usage
    6 and 7: Select channel:
    0 0 = Channel 0
    0 1 = Channel 1
    1 0 = Channel 2
    1 1 = Read-back command (8254 only)
    4 and 5: Access mode:
    0 0 = Latch count value command
    0 1 = Access mode: lobyte only
    1 0 = Access mode: hibyte only
    1 1 = Access mode: lobyte/hibyte
    1 to 3: Operating mode:
    0 0 0 = Mode 0 (interrupt on terminal count)
    0 0 1 = Mode 1 (hardware re-triggerable one-shot)
    0 1 0 = Mode 2 (rate generator)
    0 1 1 = Mode 3 (square wave generator)
    1 0 0 = Mode 4 (software triggered strobe)
    1 0 1 = Mode 5 (hardware triggered strobe)
    1 1 0 = Mode 2 (rate generator, same as 010b)
    1 1 1 = Mode 3 (square wave generator, same as 011b)
    0: BCD/Binary mode: 0 = 16-bit binary, 1 = four-digit BCD

    Собрав битовую маску, получим число: 0b10'11'011'0 = 0xB6, которое означает, что мы настраиваем Channel 2 на работу в режиме генератора прямоугольных импульсов, задавая делитель базовой частоты в виде 16-битного числа.

    Применим эту настройку, записав это число в порт 0x43.
    Для этого воспользуемся интринсиком __outbyte(), который объявлен в intrin.h:
    Код (C++):
    1.  
    2. #include <intrin.h>
    3.  
    4. void setBeeperRegime()
    5. {
    6.     __outbyte(0x43, 0xB6);
    7. }
    8.  
    После настройки режима таймера Channel 2 можно будет настраивать, задавая делитель базовой частоты 16-битным числом.
    За настройку каналов отвечают следующие порты:

    I/O port Usage
    0x40 Channel 0 data port (read/write)
    0x41 Channel 1 data port (read/write)

    0x42 Channel 2 data port (read/write)
    0x43 Mode/Command register (write only, a read is ignored)

    Нам нужен порт 0x42.

    Делитель записывается в этот порт двумя порциями: сначала младший байт, затем старший.
    Код (C++):
    1.  
    2. void setBeeperDivider(unsigned short divider)
    3. {
    4.     __outbyte(0x42, static_cast<unsigned char>(divider));
    5.     __outbyte(0x42, static_cast<unsigned char>(divider >> 8));
    6. }
    7.  
    Результирующая частота в Герцах будет равна 1193182 Гц / divider.

    Для удобства определим функцию, задающую частоту в Герцах:
    Код (C++):
    1.  
    2. void setBeeperFrequency(unsigned short freq)
    3. {
    4.     if (freq < 19) freq = 19;
    5.     const auto divider = static_cast<unsigned short>(1193182u / freq);
    6.     setBeeperDivider(divider);
    7. }
    8.  
    Здесь стоит сделать отступление: для чего нужна проверка (freq < 19)?
    Т.к. делитель ограничен 16ю битами, максимальное число, которое можно в него записать - 65'536.
    Соответственно, 1193182 / 65536 = ~18.2 Гц. Округлив вверх, получим 19 Гц.
    Если бы мы попробовали записать частоту ниже (18, 17 и т.д.) - мы бы потеряли часть делителя из-за битов, которые бы в него просто не влезли.

    Итак, таймер подготовлен, частота задана.
    Осталось дело за малым: присоединить спикер к выходу таймера.

    Для настройки спикера выделен отдельный порт - 0x61.
    Бит 0 присоединяет вход спикера к Channel 2 у PIT (1 = подключен; 0 = отключен).
    Бит 1 задаёт положение мембраны динамика (1 = "out", мембрана в верхнем положении; 0 = "in", мембрана в нижнем положении).

    Код (C++):
    1.  
    2. void startBeeper()
    3. {
    4.     const auto prev = __inbyte(0x61);
    5.     __outbyte(0x61, prev | 0b11);
    6. }
    7.  
    8. void stopBeeper()
    9. {
    10.     const auto prev = __inbyte(0x61);
    11.     __outbyte(0x61, prev & ~0b11);
    12. }
    13.  
    Итоговый код включения спикера:
    Код (C++):
    1.  
    2. #include <wdm.h>
    3.  
    4. void sleep(unsigned long ms)
    5. {
    6.     LARGE_INTEGER interval{};
    7.     interval.QuadPart = -1 * static_cast<long long>(ms) * 10000ll;
    8.     KeDelayExecutionThread(KPROCESSOR_MODE::KernelMode, false, &interval);
    9. }
    10.  
    11. void makeSomeNoise()
    12. {
    13.     setBeeperRegime();
    14.     setBeeperFrequency(1000);
    15.     startBeeper();
    16.     sleep(1000);
    17.     stopBeeper();
    18. }
    19.  
    Всё то же самое можно сделать в юзермоде, используя любой драйвер, умеющий работать с портами: WinRing0, GiveIO, EnjoyTheRing0, Kernel-Bridge, etc.

    Пример: мой синтезатор на основе WinRing0 (бинарники и исходники в аттаче):
    upload_2021-10-19_23-51-47.png
     

    Вложения:

    Последнее редактирование: 20 окт 2021
    M0rg0t, k3rnl и Vicshann нравится это.
  8. asm0day01

    asm0day01 Member

    Публикаций:
    0
    Регистрация:
    7 янв 2020
    Сообщения:
    128
    на ассемблере плииииз ;) (если можно, я не наглею просто на асме нужно мне) ну как то ;)))
    НЕ РАБОТАЕТ!
     
  9. HoShiMin

    HoShiMin Well-Known Member

    Публикаций:
    5
    Регистрация:
    17 дек 2016
    Сообщения:
    1.422
    Адрес:
    Россия, Нижний Новгород
    Так я тебе написал на ассемблере.
    Интринсики inbyte/outbyte - это прямые аналоги инструкций in и out.
     
  10. Indy_

    Indy_ Well-Known Member

    Публикаций:
    4
    Регистрация:
    29 апр 2011
    Сообщения:
    4.775
    HoShiMin,

    KbRaiseIopl() - как это работает ?

    w7 x86 после её вызова:

    Код (Text):
    1.     invoke GetProcAddress, Ebx, addr Raise$
    2.     Call Eax
    3.     pushfd
    4.     pop ecx
    5.     push 3000h
    6.     popfd
    7.     pushfd
    8.     pop ebx
    9.     mov edx,41h
    10.     in al,dx
    #GP на in соотв, контекст:

    Код (Text):
    1. $+A4     0012FC00     00000202    ebx
    2. $+A8     0012FC04     00000041    edx
    3. $+AC     0012FC08     00000246    ecx
    4. $+B0     0012FC0C     00000001    eax
    5. $+B4     0012FC10     0012FF88    ebp
    6. $+B8     0012FC14     004010A5    eip
    7. $+BC     0012FC18     0000001B    cs
    8. $+C0     0012FC1C     00010202    efl.rf ??
    Не меняется iopl.
     
  11. HoShiMin

    HoShiMin Well-Known Member

    Публикаций:
    5
    Регистрация:
    17 дек 2016
    Сообщения:
    1.422
    Адрес:
    Россия, Нижний Новгород
    x86 сейчас нет под рукой, чтобы проверить.
    Работает путём поиска EFLAGS и патча IOPL в KTRAP_FRAME.
    Там для x86, где не определён KTRAP_FRAME, захардкожены оффсеты до EFLAGS, что не очень надёжно. Возможно, они слетели и пропатчилось не то:
    Код (C++):
    1.  
    2. constexpr unsigned char KTrapFrame32Size = 0x8C;
    3. constexpr unsigned char EFlagsOffsetInKTrapFrame32 = 0x70;
    4.  
    5. PULONG eflags = IoGetInitialStack() - KTrapFrameSize + EFlagsOffsetInKTrapFrame32;
    6. *eflags |= ...;
    7.  
    Попробуй на 64х-битной системе: там KTRAP_FRAME документирован и проблем быть не должно.
    Но спасибо за репорт, проверю и поправлю уже в новом кб.
     
  12. Indy_

    Indy_ Well-Known Member

    Публикаций:
    4
    Регистрация:
    29 апр 2011
    Сообщения:
    4.775
    HoShiMin,

    IOPL плохо поддерживается и вообще вроде не поддерживается в 64 и более новых ос чем 7, но я не помню точно. Следует заводить IOPM, а не флажки.
     
  13. HoShiMin

    HoShiMin Well-Known Member

    Публикаций:
    5
    Регистрация:
    17 дек 2016
    Сообщения:
    1.422
    Адрес:
    Россия, Нижний Новгород
    Вовсе нет. Последний раз я тестил на 64х-битной десятке и IOPL работал.
    Но есть нюанс: поток не должен крутиться в оконном цикле: система сбросит IOPL при получении оконного сообщения.
    В остальном же ограничений нет: достаточно его поднять, и in/out/cli/sti можно использовать в юзермоде.

    IOPM "легально" доступна только в 32х-битных системах.
    В своём древнем драйвере EnjoyTheRing0 открывал порты и через IOPL, и через IOPM (Ke386SetAccessMap/Ke386IoSetAccessProcess, которых нет в x64), и руками патча EFLAGS в TSS.
    Но в итоге оставил только IOPL, т.к. он показался самым простым, самым универсальным (и x32, и x64) и также давал доступ к cli/sti, чего нельзя сделать через IOPM.
     
  14. Indy_

    Indy_ Well-Known Member

    Публикаций:
    4
    Регистрация:
    29 апр 2011
    Сообщения:
    4.775
    HoShiMin,

    Понятно, а зачем колхозить вытягивая фрейм со дна стека, он ведь рекурсивный и указатель в поток сохраняется(KTHREAD) ?

    > система сбросит IOPL

    Кто его знает что она сбросит. Я на днях импорт вмп пытался восстановить, так вот не смотря на сурки и такой же диз в чём этого быть не должно, планировщик сбрасывает селекторы. Так что эта среда - контекст очень не надёжна..
     
  15. HoShiMin

    HoShiMin Well-Known Member

    Публикаций:
    5
    Регистрация:
    17 дек 2016
    Сообщения:
    1.422
    Адрес:
    Россия, Нижний Новгород
    Указатель-то, может, и сохраняется, только как его найти?
    Вытягивание со дна хотя бы более-менее стабильно: размер KTRAP_FRAME фиксирован, структура документирована (пусть и только на x64).
    А как быть с KTHREAD? Она же рискует поменяться при первом же обновлении системы.
    --- Сообщение объединено, 25 окт 2021 ---
    В вмп что-то основано на их изменении?
     
  16. Indy_

    Indy_ Well-Known Member

    Публикаций:
    4
    Регистрация:
    29 апр 2011
    Сообщения:
    4.775
    HoShiMin,

    > А как быть с KTHREAD?

    Не проблема же смещение найти, ловушку распарсить вариантов очень много.

    > В вмп что-то основано на их изменении?

    Нет, решение такое - передать управление в RX сегмент. Если загрузить в legacy cs -> ds, то шедулер поправит на кванте в дефолтное значение и сегмент, те всё ап станет открыто на запись. Это так же не надёжно как и манипуляции флажками.
     
  17. asm0day01

    asm0day01 Member

    Публикаций:
    0
    Регистрация:
    7 янв 2020
    Сообщения:
    128
    народ, дайте драйвер для ковыряния хоть самый примитивный и инфу к этому всему (если можно) %D
     
  18. HoShiMin

    HoShiMin Well-Known Member

    Публикаций:
    5
    Регистрация:
    17 дек 2016
    Сообщения:
    1.422
    Адрес:
    Россия, Нижний Новгород
    А что именно тебе неясно из того, что написано выше? Я тебе дал ссылку на скачивание драйвера и подробное описание
     
  19. asm0day01

    asm0day01 Member

    Публикаций:
    0
    Регистрация:
    7 янв 2020
    Сообщения:
    128
    не работает (
     
  20. HoShiMin

    HoShiMin Well-Known Member

    Публикаций:
    5
    Регистрация:
    17 дек 2016
    Сообщения:
    1.422
    Адрес:
    Россия, Нижний Новгород
    Что именно? Покажи код, который ты написал, и который не работает