работа с SERVICE_DESCRIPTOR_TABLE и win32k

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

  1. hilete

    hilete New Member

    Публикаций:
    0
    Регистрация:
    6 сен 2008
    Сообщения:
    28
    FindShadowTable.asm
    Код (Text):
    1.     invoke GetServiceDescriptorTableShadowAddress
    2. .if eax != NULL
    3.     mov eax,[eax]
    4.     mov eax,[eax]
    5. .endif
    работает отлично

    Код (Text):
    1.     invoke GetServiceDescriptorTableShadowAddress
    2. .if eax != NULL
    3.     add eax,10h
    4.     mov eax,[eax] ; eax == BF997600 (kproccheck показывает этот же адрес)
    5.     mov eax,[eax] ;<-PAGE_FAULT (MmIsAddressValid == 0)
    6. .endif
    BSoD
     
  2. Four-F

    Four-F New Member

    Публикаций:
    0
    Регистрация:
    31 авг 2002
    Сообщения:
    1.237
    Смутно уже всё помню ;), но думаю проблема в том, что GetServiceDescriptorTableShadowAddress вызывается из контекста системного процесса, например из DriverEntry. Есть два вида потоков: GUI и не-GUI. Не-GUI потокам не нужны сервисы win32k. Все потоки изначально не-GUI. Как только поток делает свой первый вызов к какой-либо функции GDI или USER, то система чего-то там меняет в его сервисной таблице (то ли добавляет указатель на сервисную таблицу win32k, то ли чего там перегруппирует). К тому же, кажется сервисная таблица win32k лежит на адресном пространстве сеанса (session address space). У системного процесса нет туда доступа, кажись. Вобщем детали я скорее всего путаю, но идея должна быть понятна. Если просто добавить в драйвер обработчик IRP_MJ_DEVICE_CONTROL, дернуть его из юзера и уже в контексте юзерного потока вызывать GetServiceDescriptorTableShadowAddress, то тогда твой код скорее всего заработает без бсодов. Или же придется переключаться на контекст любого GUI потока и оттуда вызывать GetServiceDescriptorTableShadowAddress.

    Кажись где-то так. Погугли детали.
     
  3. Twister

    Twister New Member

    Публикаций:
    0
    Регистрация:
    12 окт 2005
    Сообщения:
    720
    Адрес:
    Алматы
    hilete
    Four-F все правильно сказал. Переключись на csrss.exe и там работай с Shadow
     
  4. hilete

    hilete New Member

    Публикаций:
    0
    Регистрация:
    6 сен 2008
    Сообщения:
    28
    я читал конференции и статьи, это я уяснил хорошо :) а вот про "session address space, у системного процесса нет туда доступа" - нигде не встречал.
    осталось научиться "переключаться на контекст любого GUI потока"...
    а вообще, большое спасибо за направление. буду изучать дальше. :)

    а насчет погуглить детали - это вряд ли. почти все что находится так или иначе относится к твоим наработкам или упоминается твое имя. :)
     
  5. Four-F

    Four-F New Member

    Публикаций:
    0
    Регистрация:
    31 авг 2002
    Сообщения:
    1.237
    Это явное преувеличение, гугли глубже ;)
     
  6. hilete

    hilete New Member

    Публикаций:
    0
    Регистрация:
    6 сен 2008
    Сообщения:
    28
    если я знаю адрес списка, я могу с ним работать из user-mode'а посредством NtMapViewOfSection?

    Вызов GetServiceDescriptorTableShadowAddress из DispatchControl задал мне больше вопросов. теперь адрес таблицы вообще не возвращается. KeServiceDescriptorTable и адрес KTHREAD.ServiceTable (этого потока) не равны!!! :) как следствие - GetServiceDescriptorTableShadowAddress не определяет смещение по которому в KTHREAD находится ServiceTable.
     
  7. Four-F

    Four-F New Member

    Публикаций:
    0
    Регистрация:
    31 авг 2002
    Сообщения:
    1.237
    хз. Поищи исходники всяких анхукеров SSDT и посмотри как они работают с таблицей. В буржунете точно есть статьи по теме.

    Вспоминать некогда. Вот кусок из работающего драйвера.

    Код (Text):
    1. SYSTEM_SERVICE_TABLE STRUCT     ; sizeof = 10h
    2.     pServiceTable   PVOID       ?   ; array of entry points
    3.     pCounterTable   PDWORD      ?   ; array of usage counters
    4.     dwServiceLimit  DWORD       ?   ; number of table entries
    5.     pArgumentTable  PBYTE       ?   ; array of byte counts
    6. SYSTEM_SERVICE_TABLE ENDS
    7. PSYSTEM_SERVICE_TABLE typedef ptr SYSTEM_SERVICE_TABLE
    8.  
    9. SERVICE_DESCRIPTOR_TABLE STRUCT     ; sizeof = 40h
    10.     ntoskrnl    SYSTEM_SERVICE_TABLE    <>  ; ntoskrnl.exe (native api)
    11.     win32k      SYSTEM_SERVICE_TABLE    <>  ; win32k.sys   (gdi/user)
    12.     iis         SYSTEM_SERVICE_TABLE    <>  ; Internet Information Services
    13.     Table4      SYSTEM_SERVICE_TABLE    <>  ; reserved
    14. SERVICE_DESCRIPTOR_TABLE ENDS
    15. PSERVICE_DESCRIPTOR_TABLE typedef ptr SERVICE_DESCRIPTOR_TABLE
    16.  
    17. g_dwServiceTableFieldOffset             DWORD                       ?
    18. g_pKeServiceDescriptorTableShadow       PSERVICE_DESCRIPTOR_TABLE   ?
    19.  
    20. DispatchControl proc uses esi edi ebx pDeviceObject:PDEVICE_OBJECT, pIrp:PIRP
    21.  
    22.     mov esi, pIrp
    23.     assume esi:ptr _IRP
    24.  
    25.     mov [esi].IoStatus.Status, STATUS_UNSUCCESSFUL
    26.     and [esi].IoStatus.Information, 0
    27.  
    28.     IoGetCurrentIrpStackLocation esi
    29.     mov edi, eax
    30.     assume edi:ptr IO_STACK_LOCATION
    31.  
    32.     mov eax, [edi].Parameters.DeviceIoControl.IoControlCode
    33.     .if eax == IOCTL_FIND_SERVICE_TABLE_FIELD_OFFSET
    34.  
    35.         ; Find KTHREAD.ServiceTable field
    36.         ; For non-GUI threads this field == KeServiceDescriptorTable
    37.         ; and it points to ServiceDescriptorTable
    38.  
    39.         invoke KeGetCurrentThread
    40.         mov edx, KeServiceDescriptorTable
    41.         mov edx, [edx]
    42.         mov ecx, 200h-4
    43.         .while ecx
    44.             .break .if dword ptr [eax][ecx] == edx
    45.             dec ecx
    46.         .endw
    47.         mov g_dwServiceTableFieldOffset, ecx
    48.         .if ecx != 0
    49.             ; ecx = offset to ServiceTable field in KTHREAD structure
    50.             mov [esi].IoStatus.Status, STATUS_SUCCESS
    51.         .endif
    52.  
    53.     .elseif eax == IOCTL_FIND_SHADOW_TABLE_ADDRESS
    54.  
    55.         .if g_dwServiceTableFieldOffset != 0
    56.  
    57.             ; Find not exported KeServiceDescriptorTableShadow.
    58.             ; The calling thread should be GUI one.
    59.             ; So its KTHREAD.ServiceTable == KeServiceDescriptorTableShadow.
    60.             ; And we already know the right offset to this field
    61.  
    62.             invoke KeGetCurrentThread
    63.             mov ecx, g_dwServiceTableFieldOffset
    64.             mov eax, dword ptr [eax][ecx]
    65.             mov edx, KeServiceDescriptorTable
    66.             mov edx, [edx]
    67.             .if eax != edx
    68.                 ; If KTHREAD.ServiceTable != KeServiceDescriptorTable
    69.                 ; it nothing more then KeServiceDescriptorTableShadow.
    70.                 mov g_pKeServiceDescriptorTableShadow, eax
    71.                 mov [esi].IoStatus.Status, STATUS_SUCCESS
    72. IFDEF DBG
    73.                 invoke DbgPrint, $CTA0("KeServiceDescriptorTableShadow found at address: %08X\n"), \
    74.                                     g_pKeServiceDescriptorTableShadow
    75. ENDIF
    76.             .endif
    77.  
    78.         .endif
    79.  
    80.     .else
    81.         mov [esi].IoStatus.Status, STATUS_INVALID_DEVICE_REQUEST
    82.     .endif
    83.  
    84.     push [esi].IoStatus.Status
    85.  
    86.     assume esi:nothing
    87.     assume edi:nothing
    88.  
    89.     fastcall IofCompleteRequest, esi, IO_NO_INCREMENT
    90.  
    91.     pop eax
    92.     ret
    93.  
    94. DispatchControl endp
     
  8. hilete

    hilete New Member

    Публикаций:
    0
    Регистрация:
    6 сен 2008
    Сообщения:
    28
    В общем как я говорил, KeServiceDescriptorTable и KTHREAD.ServiceTable хранят разные адреса (и смещение не определяется). НО! я прямо дал смещение для KTHREAD == E0h, и доступ к адресу BF997600 из DispatchControl есть! собственно мне большего и не надо. Спасибо большое Four-F, Twister!
     
  9. Four-F

    Four-F New Member

    Публикаций:
    0
    Регистрация:
    31 авг 2002
    Сообщения:
    1.237
    Надеюсь ты понимаешь, что смещения "гуляют" от системы к системе.
     
  10. hilete

    hilete New Member

    Публикаций:
    0
    Регистрация:
    6 сен 2008
    Сообщения:
    28
    безусловно. но мне это нужно на моем компе только. да и я всегда могу получать нужные адреса (тот же ~BF997600) в DriverEntry сначала (вызванная оттуда функция нормально получала адрес shadow таблицы), а уже потом ломиться по ним из DispatchControl. в общем надо установить закономерность когда и что происходит с этими адресами и работать.
     
  11. hilete

    hilete New Member

    Публикаций:
    0
    Регистрация:
    6 сен 2008
    Сообщения:
    28
    Four-F, извини, я опять затупил... DbgPrint оказывается GUI функция и я ее вызывал как раз перед сравнением (люблю эту функцию просто), поэтому получалось что "KeServiceDescriptorTable и KTHREAD.ServiceTable хранят разные адреса", т.к. поток переводился в разряд GUI'шных... :dntknw: убрал DbgPrint - все как часы.
     
  12. Twister

    Twister New Member

    Публикаций:
    0
    Регистрация:
    12 окт 2005
    Сообщения:
    720
    Адрес:
    Алматы
    Нет, ни чего подобного DbgPrint() не делает. Скорее всего ее вызов у тебя "портил" значения регистров.
     
  13. hilete

    hilete New Member

    Публикаций:
    0
    Регистрация:
    6 сен 2008
    Сообщения:
    28
    Twister, я проверю эту мысль. Наверное ты прав.

    Все. Добавил сервис, научился запускать его с User Mode. Кому интересно - могу выложить сурсы.

    Пока еще только не понял можно ли подменять KTHREAD.ServiceTable. Но это вроде не за горами.