kernel debugger

Тема в разделе "WASM.NT.KERNEL", создана пользователем wasm_test, 18 дек 2008.

  1. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    Регистрация:
    24 ноя 2006
    Сообщения:
    5.582
    Я сейчас решил с нуля писать свой отладчик, который писал год назад.
    Решил сделать его локальным, для удаленной отладки меня сейчас устравиает и kd/windbg (com-port), visual softice (ethernet)

    Проект : http://code.google.com/p/ngdbg/

    Технология вывода: (Другое опишу позже)

    Выводить своё изображение можно :
    1) прямым выводом в фреймбуффер. На некоторых видеокартах изображение идет подряд - пиксель за пикселем, строчка за строчкой в фреймбуффере. На некоторых - новые строчки могут выравниваться по границе страницы или же вообще фреймбуффер может иметь блочную структуру.
    2) манипуляциями с win32k и драйвером дисплея.
    Если ты почитаешь MSDN, то найдешь там функции Eng** от win32k graphics engine. Увидишь, что есть много функции рисования на виртуальных "поверхностях" (surface objects, struct _SURFOBJ*). Например, EngLineTo.
    Они производят построение изображения. Поверхность можно создать через EngCreateBitmap. Можно даже загрузить с диска готовое изображение bmp. и сделать из него поверхность.
    Проблема в том, что этими функциями ты можешь создать виртуальное изображение на виртуальной поверхности (типа hdc в юзермоде), но тебе в конце концов потребуется перенести свое изображение на поверхность физического дисплея. Этим занимается функция видеодрайвера DrvCopyBits. Как найти ее - писать здесь и сейчас я сомневаюсь, что следует, поскольку хоть один человечек (PROFi, привеееет :lol: ) скидывал мне год назад технологию вывода свою, которую я если честно год назад нифига не понял, поскольку по этой теме нифига не знал, а сейчас все проделал самостоятельно и просто ради интереса вспомнил про тот случай. Та технология хоть и не имеет ничего общего с поиском DrvCopyBits, который я затеял сейчас, но некоторые люди все равно могут усмотреть аналогию и обвинить меня в плагиате.
    Ну да ладно, все равно отладчик я планирую делать OpenSource и в принципе исходнеы коды доступны и сейчас в http://code.google.com/p/ngdbg/source/browse/trunk/.
    Задача заключается в следующем: видеодрайвер реализует функции, которые отвечают за физическое рисование и копирование бит на физическую поверхность дисплея, производя необходимые преобразования в случае нелинейности фреймбуффера и в конце концов делает memmove, поэтому нам нужен указатель на его DrvCopyBits, так же нам нужен SURFOBJ* физической поверхности.

    С выводом графики в Windows связаны два драйвера:
    1) драйвер минипорта видео, который является стандартным драйвером, драйвером видеопорта его делает лишь импорт из videoprt.sys и вызов VideoPortInitialize
    2) драйвер дисплея .dll, который на самом деле никакой не dll, а самый настоящий драйвер режима ядра, но не обычный - его загружает подсистема win32 в момент загрузки системы или в рантайме при установке нового видеоадаптера и он может импортировать только из win32k.sys. Драйвер минипорта ничем не примечателен - он отвечает за фактическую работу с аппаратной частью - собственно видеокартой, а драйвер дисплея представляет некоторый интерес - он предоставляет подсистеме win32 функции, в которых заложена логика того, как работать с фреймбуффером, который можно получить от драйвера минипорта запросом IOCTL_VIDEO_MAP_VIDEO_MEMORY. Далеко не на всех видеокартах фреймбуффер содержит подряд пиксели экрана, например у меня на ноутбуке фреймбуффер содержит scan-lines (так Windows называет горизонтальную линию пикселей), выровненные на границу страницы. То есть если разрешение стоит 1280x800, то каждая новая строчка начинается не со смещения nLine * 1280 * sizeof(PIXEL), а со смещения ALIGN_UP (nLine*1280*sizeof(PIXEL), PAGE_SIZE). На других видеокартах могут быть свои причуды. Всем этим управляет драйвер дисплея, фунция DrvCopyBits
    которого как раз копирует пиксели с win32-поверхности (SURFOBJ) на поверхность экрана, производя, при необходимости, нужные преобразования (как минимум, нужно преобразовать обратный порядок бит, который используется в Windows и в bmp файлах в прямой порядок на экране). Поэтому для корректного вывода нам потребуется две вещи - адрес DrvCopyBits драйвера дисплея и указатель на поверхность экрана SURFOBJ*. Драйвер основного дисплея загружается при старте системы, инициализация win32 подсистемы csrss.exe вызывает функцию win32k!NtUserInitialize, которая делает
    NtUserChangeDisplaySettings, а она вызывает win32k!ldevLoadDriver:
    fa0f2980 bf8ba311 vmx_fb!DrvEnableDriver+0x11
    fa0f29ac bf8ba3c6 win32k!ldevLoadDriver+0x71
    fa0f29c4 bf8bd52d win32k!ldevGetDriverModes+0x1b
    fa0f29f4 bf8b8cde win32k!DrvBuildDevmodeList+0xa4
    fa0f2a7c bf8b3221 win32k!DrvProbeAndCaptureDevmode+0x408
    fa0f2bf4 bf8b9423 win32k!DrvCreateMDEV+0x42d
    fa0f2ce8 bf8b624e win32k!DrvChangeDisplaySettings+0x2e5
    fa0f2d28 bf8b61bc win32k!InitVideo+0x3e
    fa0f2d48 bf8b71fe win32k!UserInitialize+0x14d
    fa0f2d50 8053c808 win32k!NtUserInitialize+0x87
    fa0f2d50 7c90eb94 nt!KiFastCallEntry+0xf8
    0015fd80 75b3a68e ntdll!KiFastSystemCallRet
    0015fdb0 75b13472 winsrv!NtUserInitialize+0xc
    0015fe20 75b1301b CSRSRV!CsrLoadServerDll+0x1a0
    0015ff74 75b130f3 CSRSRV!CsrParseServerCommandLine+0x2d6
    0015ff88 4a68115d CSRSRV!CsrServerInitialization+0x95
    0015ffa8 4a6818d7 csrss!main+0x4f
    0015fff4 00000000 csrss!NtProcessStartup+0x1d2
    (не спрашивайте откуда у меня символы для дллек вмвари, это на самом деле мой собственный mirror-драйвер, которым я подменил оригинальный в вмваре и все запросы он транслировал в оригинальный - мне так легче было изучить как работает драйвер дисплоея)

    Этот стек вызовов показан с VMWare, где драйвер дисплея - vmx_fb.dll. Точка входа драйвера дисплея называется DrvEnableDriver, она имеет следующий прототип:
    BOOLEAN NTAPI DrvEnableDriver(
    ULONG iEngineVersion,
    ULONG cj,
    PDRVENABLEDATA pded
    );
    Эта функция производит много полезных вещей, но на выходе она обязана записать в PDRVENABLEDATA массив Callback'ов драйвера (для примера как работает драйвер дисплея - посмотри \WINDDK\2600.1106\src\video\displays\mirror\disp\enable.c и другие файлы из этой директории). Нам нужен этот массив каллбеков.
    Я сделал следующим образом (см. http://code.google.com/p/ngdbg/source/browse/trunk/ngvid.cpp и функцию REINITIALIZE_ADAPTER()):
    я подгружаю себе копию видеодрайвера функцией EngLoadImage (как мне удается использовать Eng* в обычном драйвере с такой легкостью - другой вопрос:) это тоже можно найти в сорцах, у меня используется фишка с ложным импортом и его динамической подменой) и просто вызываю ее ентри. Она не производит никаких действий по инициализации видеокарты, поскольку драйвер дисплея обычно подгружается несколько раз. Поэтому я могу смело ее вызвать и получить себе массив каллбеков. После этого драйвер выгружается. Я ищу в массиве каллбеков DrvCopyBits, считаю её RVA относительно базы копии видеодрайвера. После этого я добавляю VA загруженного нормального видеодрайвера и получаю реальный адрес DrvCopyBits.
    Первая часть задачи решена. Начинаем решать вторую часть - чтобы получить SURFOBJ* поверности экрана, я ставлю сплайсинговый хук на DrvCopyBits. Не думаю, что юзеры во время загрузки моего драйвера будут интенсивно водить мышкой, поэтому вряд ли функция будет вызываться часто. DrvCopyBits имеет такой прототип:
    BOOLEAN
    NTAPI
    DrvCopyBits(
    OUT _SURFOBJ *psoDst,
    IN _SURFOBJ *psoSrc,
    IN VOID *pco,
    IN VOID *pxlo,
    IN VOID *prclDst,
    IN VOID *pptlSrc
    );
    Нас интересует значение psoDst - функция обычно занимается копированием НА поверхность экрана. Поэтому в обработчике хука мы делаем некоторые проверки на psoDst (я делаю проверки на размер поверхности - если она больше или равна, чем 640х480, очевидно это главная поверхность) и записываю себе её как главную поверхность. После этого хук снимается.

    Задача решена. Теперь для вывода нужно создать себе поверхность через EngCreateBitmap, рисовать там через Eng*** функции, а потом скопировать изображение на первичную главную поверхность экрана через DrvCopyBits.
    Как это все происходит можно посмотреть в http://code.google.com/p/ngdbg/source/browse/trunk/worker.cpp - там содержатся функции, отвечающие за интерфейсную часть отладчика (в отличие от http://code.google.com/p/ngdbg/source/browse/trunk/gui.cpp, где содержится небольшой набор GDI-аналогов для вывода текста на экран и других шалостей с собственным форматом шрифтов). Достаточно посмотреть на функцию DisplayBuffers или WR_ENTER_DEBUGGER (нет, не все функции у меня называются заглавными буквами - только две, уже не помню почему :lol: ).
     
  2. BlackParrot

    BlackParrot New Member

    Публикаций:
    0
    Регистрация:
    19 фев 2009
    Сообщения:
    163
    Great
    Копирайтя я прозевал, извиняюсь. Проект очень крутой. Спасибо за опенсорс.
     
  3. ohne

    ohne New Member

    Публикаций:
    0
    Регистрация:
    28 фев 2009
    Сообщения:
    431
    там кстати копирайты есть
    CADT точно указан
    http://code.google.com/p/ngdbg/source/browse/trunk/Disasm.h
     
  4. Nerka

    Nerka New Member

    Публикаций:
    0
    Регистрация:
    14 мар 2009
    Сообщения:
    16
    Spasibo. Posmotrel, davolno interesno. Ja tozhe dlia sebia sdelal kmd, no on otlichaetsia tem shto bolshe softice napominaet (hooki na interaptah, i vivod priamo na pci framebuffer (do novih geforce on lineinij i rabotaet nadezhno s naimenshimi izmenenijami v sisteme). A vot naschet video draiverov i otkaza zagruzki kogda importiruetsa shto to ne iz win32k.sys, est' prostoe reshenie (nu kaneshno krome ioctl na miniport) - mozhno sdelat' obiknovenij driver, eksportirovat' iz nevo nuzhnie funkciji, togda ego zagruzhat' s EngLoadImage, naiti adresa s EngFindImageProcAddress i vipolnat' ih (analog loadlibrary, getprocaddress v usermode).

    Izvinite za translit, ja sam litovec i na ruskoi klaviature pol dnia bi pechatal :)
     
  5. Aquila

    Aquila Самурай дзена

    Публикаций:
    0
    Регистрация:
    30 авг 2002
    Сообщения:
    1.467
    Адрес:
    Russia, Moscow
    Nerka
    Если есть проблемы с русскоязычной клавиатурой, то используй транслитератор (например, http://www.translit.ru/ ).
     
  6. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    Регистрация:
    24 ноя 2006
    Сообщения:
    5.582
    Nerka
    Насчет драйверов была такая идея. Все равно не потребовалась, т.к. драйвера минипорта я отбросил из своего решения.
     
  7. Nerka

    Nerka New Member

    Публикаций:
    0
    Регистрация:
    14 мар 2009
    Сообщения:
    16
    спасибо, буду знать :)
     
  8. Nerka

    Nerka New Member

    Публикаций:
    0
    Регистрация:
    14 мар 2009
    Сообщения:
    16
    Great, я вот еще думал про вывод прямо через crt порта, но мне показалось довольно большая возня копаться в crt регистрах, зная то что стандарты такие как vesa например неиспользуетса и черт знает как потом все это востоновить чтобы nvidia не ругалась и смогла дальше работать. Во всяком случае именно с выводом самые трудные проблемы. Другие части у меня практически без изменений работают под windows, linux и т.д. на х86 (имея в виду что перехваты на прерываниях). Я еще до конца не пересмотрел все соурсы, но у меня сразу же вопрос... например при сингл степ отпускаем вывод до следующей инструкции.. Если ты все выводишь через GDI, как ты справляешься со всеми изменениями которые проходит во время вывода? Ведь черт знает что в это время драивер делает. Или ты уверен что в DrvBitBlt (или DrvCopyBits) будет простое memcpy которое ничего ни меняет и это можно утоить?
     
  9. SmanxX1

    SmanxX1 Member

    Публикаций:
    0
    Регистрация:
    18 июн 2008
    Сообщения:
    139
    Что-то темка опустилась.
    Продвижения хоть есть или проект похоронен?
     
  10. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    Регистрация:
    24 ноя 2006
    Сообщения:
    5.582
    Дописывается по мере появления свободного времени.