Получение индекса текущего сервиса SSDT внутри его обработчика

Тема в разделе "WASM.NT.KERNEL", создана пользователем m0zg, 2 июн 2011.

  1. m0zg

    m0zg New Member

    Публикаций:
    0
    Регистрация:
    1 июл 2009
    Сообщения:
    21
    Добрый день!
    Пытаюсь сделать один свой обработчик на несколько сервисов SSDT с одинаковым числом аргументов. Массив оригинальной ServiceTable полностью сохранен. Чтобы вызвать из сохраненной таблицы оригинальный обработчик, нужно, находясь в подмененном обработчике, получить индекс по которому сервис был вызван системой. Собственно как этот индекс получить?
     
  2. assorted

    assorted New Member

    Публикаций:
    0
    Регистрация:
    7 авг 2006
    Сообщения:
    227
    Никак. Твой обработчик может оказаться не первым (а вообще EAX до первого обработчика интересно без изменений дойдет?). Делай разные.
     
  3. m0zg

    m0zg New Member

    Публикаций:
    0
    Регистрация:
    1 июл 2009
    Сообщения:
    21
    А если все обработчики будут мои, он все равно может оказаться не первым?
    Собственно, если предположить, что он будет первый, то где смотреть индекс?
     
  4. assorted

    assorted New Member

    Публикаций:
    0
    Регистрация:
    7 авг 2006
    Сообщения:
    227
    Скорее всего никак.
     
  5. m0zg

    m0zg New Member

    Публикаций:
    0
    Регистрация:
    1 июл 2009
    Сообщения:
    21
    Теперь Вы сомневаетесь?
    Думаю если система знала какой сейчас надо вызвать адрес из таблицы, значит и индекс где-то хранится. Как минимум вроде можно INT 2E перехватить и сохранить куда-нибудь AX. Если сейчас в обработчике смотреть, то в AX какой-то мусор.
     
  6. assorted

    assorted New Member

    Публикаций:
    0
    Регистрация:
    7 авг 2006
    Сообщения:
    227
    Подменив INT 2E и sysenter можно разумеется получить номер сервиса. Речь шла об SSDT обработчике - из него нельзя.
     
  7. TSS

    TSS New Member

    Публикаций:
    0
    Регистрация:
    13 апр 2009
    Сообщения:
    494
    http://kitrap08.blogspot.com/2011/02/id.html
     
  8. gaeprust

    gaeprust New Member

    Публикаций:
    0
    Регистрация:
    2 май 2011
    Сообщения:
    188
    Eax = Id & SERVICE_NUMBER_MASK(0x1000H - 1).

    В T-фрейме Eax = Id. Иначе найти в SST значение в Ebx. Индекс указателя делённый на 4 будет номером сервиса.
     
  9. m0zg

    m0zg New Member

    Публикаций:
    0
    Регистрация:
    1 июл 2009
    Сообщения:
    21
    А не подскажете как это дело перевести на C или хотя бы asm? Просто я про трап фрейм (Т-фрейм?) впервые слышу...
     
  10. klzlk

    klzlk New Member

    Публикаций:
    0
    Регистрация:
    2 июн 2011
    Сообщения:
    449
    m0zg
    Както так:
    Код (Text):
    1.     mov edi,dword ptr ds:[pSST]
    2.     mov ecx,dword ptr ds:[SizeOfSST]    ; /4
    3.     mov eax,ebx ; @Nt*
    4.     repne scasd
    5.     shr eax,2   ; /4, Id + 1
    6.     dec eax     ; Id
    А с T-фреймом всё просто:
     
  11. Xml

    Xml New Member

    Публикаций:
    0
    Регистрация:
    18 май 2011
    Сообщения:
    54
    klzlk
    как же так?
     
  12. m0zg

    m0zg New Member

    Публикаций:
    0
    Регистрация:
    1 июл 2009
    Сообщения:
    21
    Пока что работает только вот так:
    Код (Text):
    1.     ULONG Id;
    2.     ULONG SavedEbx = 0;
    3.  
    4.     __asm { mov SavedEbx, ebx }
    5.  
    6.     ULONG n = KeServiceDescriptorTable->ntoskrnl.ServiceLimit;
    7.     PULONG pSST = (PULONG)KeServiceDescriptorTable->ntoskrnl.ServiceTable;
    8.     Id = 0;
    9.     while(Id < n)
    10.     {
    11.         if(SavedEbx == pSST[Id])
    12.             break; //Id == index
    13.         Id++;
    14.     }
    Но это будет тормозить т.к. перебирать придется до 667 или 284 значений в XP

    Дальше вот такой код не работает:
    Код (Text):
    1.     __asm
    2.     {
    3.         mov edi,dword ptr ds:[pSST]
    4.         mov ecx,dword ptr ds:[n]
    5.         mov eax,SavedEbx
    6.         repne scasd
    7.         shr eax, 2
    8.         dec eax
    9.         mov Id, eax
    10.     }
    в Id совсем не то что нужно

    Код (Text):
    1.             PETHREAD pEThread = PsGetCurrentThread();
    2.             PKTHREAD pKThread = &pEThread->Tcb;
    3.             PKTRAP_FRAME pKTrapFrame = pKThread->TrapFrame;
    4.             ULONG eax = pKTrapFrame->Eax;
    В eax все что угодно, только не индекс
     
  13. klzlk

    klzlk New Member

    Публикаций:
    0
    Регистрация:
    2 июн 2011
    Сообщения:
    449
    m0zg
    Аа ну я забыл sub edi,dword ptr ds:[pSST]/mov eax,edi(это же смещение элемента в массиве), так как напечатал это второй раз мошинально(предыдущий мой акк аверы забанили).
     
  14. Charlief

    Charlief New Member

    Публикаций:
    0
    Регистрация:
    17 авг 2010
    Сообщения:
    129
    Функции из ServiceTable в Windows XP вызываются внутри диспетчера системных сервисов _KiFastCallEntry командой call ebx следовательно находясь в подмененном обработчике отняв от ebx адрес ServiceTable получим смещение в таблице сервисов, смещение разделив на 4 получим индекс.
    Номер сервиса котрый в функции API записывается в eax разбивается на битовые поля. 12 младших бит – индекс в таблице ServiceTable, следующие два – индекс таблицы в SDT
    Если индекс равен или превышает ServiceLimit то используется _KeServiceDescriptorTableShadow.
     
  15. m0zg

    m0zg New Member

    Публикаций:
    0
    Регистрация:
    1 июл 2009
    Сообщения:
    21
    Все равно непонятно как это должно работать (с ассемблером не дружу к сожалению)
    если вот так:
    Код (Text):
    1.         sub edi,dword ptr ds:[pSST]
    2.         mov ecx,dword ptr ds:[n]
    3.         mov eax, ebx
    4.         repne scasd ;Access violation
    5.         shr eax, 2
    6.         dec eax
    то куда девать mov eax,edi?

    Может лучше объясните как из _KTRAP_FRAME выдернуть индекс?
     
  16. klzlk

    klzlk New Member

    Публикаций:
    0
    Регистрация:
    2 июн 2011
    Сообщения:
    449
    m0zg
    Код (Text):
    1.     mov edi,dword ptr ds:[pSST]
    2.     mov ecx,dword ptr ds:[SizeOfSST]    ; /4
    3.     mov eax,ebx    ; @Nt*
    4.     repne scasd
    5.     sub edi,dword ptr ds:[pSST]
    6.     mov eax,edi
    7.     shr eax,2    ; /4, Id + 1
    8.     dec eax        ; Id
    Простейший код ведь. Есть у вас массив значений, Dim[1] = a, Dim[2] = b.. etc. Нужно найти в массиве b. Тоесть перечислить элементы массива и выбрать нужный. Тогда разность адреса элемента и начала массива делённая на размер элемента будет его индексом.

    Charlief
    Неа, так не получится. В Ebx адрес сервиса, тоесть Nt-хэндлера. Call Ebx != Call [ebx].
     
  17. klzlk

    klzlk New Member

    Публикаций:
    0
    Регистрация:
    2 июн 2011
    Сообщения:
    449
    Ну он в регистре Eax. Прочитать из структуры.
     
  18. m0zg

    m0zg New Member

    Публикаций:
    0
    Регистрация:
    1 июл 2009
    Сообщения:
    21
    Ну в общем Ваш код работает, но это ведь получается почти то же самое что
    Код (Text):
    1. ULONG GetId(ULONG ebx)
    2. {
    3.     ULONG n = KeServiceDescriptorTable->ntoskrnl.ServiceLimit;
    4.     PULONG pSST = (PULONG)KeServiceDescriptorTable->ntoskrnl.ServiceTable;
    5.     ULONG idx = 0;
    6.     while(idx < n)
    7.     {
    8.         if(ebx == pSST[idx])
    9.             break;
    10.         idx++;
    11.     }
    12.     return idx;
    13. }
    то есть перебор - из-за быстродействия не хотелось бы применять такой способ во время перехвата
     
  19. klzlk

    klzlk New Member

    Публикаций:
    0
    Регистрация:
    2 июн 2011
    Сообщения:
    449
    Длительность межквантового простоя вашего треда много больше времени выборки элемента из массива. Задержками можно пренебречь - визуально это нельзя обнаружить.

    Тогда извлеките индекс из T-фрейма(но данный способ не надёжен, так как сервисы не обязательно через диспетчер вызываются).
     
  20. m0zg

    m0zg New Member

    Публикаций:
    0
    Регистрация:
    1 июл 2009
    Сообщения:
    21
    Пробовал вот так
    Код (Text):
    1. PETHREAD pEThread = PsGetCurrentThread();
    2.             PKTHREAD pKThread = &pEThread->Tcb;
    3.             PKTRAP_FRAME pKTrapFrame = pKThread->TrapFrame;
    4.             ULONG eax = pKTrapFrame->Eax;
    в eax совсем не то