Как из драйвера получить текущую раскладку клавиатуры (LCID)

Тема в разделе "WASM.WIN32", создана пользователем Guest, 8 сен 2006.

  1. Guest

    Guest Guest

    Публикаций:
    0
    Ситуация следующая: нужно из Ring-0 (из драйвера) получить текущую раскладку клавиатуры (LCID). В обычном Ring-3 можно получить раскладку используя GetActiveLayout. Под Ring-0 это можно реализовать так как показано ниже (у меня XP SP2, поэтому как это будет работать на 2k не знаю), но относится это будет только к текущему потоку, поэтому если переключится на другую программу то нифига работать не будет (ибо fs:[124h] - PETHREAD CurrentThread, а значит это будет поток драйвера, или поток программы сделавшей запрос через DeviceIO).

    Код (Text):
    1. DWORD GetKeyboardLayout(void)
    2. {
    3.     PVOID pWinThread = NULL;
    4.     __asm
    5.     {
    6.         mov eax, fs:[124h]
    7.         mov eax, [eax+130h]
    8.         mov pWinThread, eax
    9.     }
    10.     if (!pWinThread)
    11.     {
    12.         DbgPrint("--- NOT FOUND WIN32_THREAD ---\n");
    13.         return 0;
    14.     }
    15.     __asm {
    16.         mov eax, pWinThread
    17.         mov eax, [eax+0x34]
    18.         mov pWinThread, eax
    19.     }
    20.     if (!pWinThread)
    21.     {
    22.         DbgPrint("--- NOT FOUND LAYOUT ---\n");
    23.         return 0;
    24.     }
    25.     _asm{
    26.         mov eax, pWinThread
    27.         mov eax, [eax+0x14]
    28.     }
    29. }
    Вот этот код ищет активное окно (через него можно и поток с LCID найти), но опять только окно текущего процесса:
    Код (Text):
    1. DWORD GetActiveWindow()
    2. {
    3.     PVOID pWinThread = NULL;
    4.     __asm{
    5.         mov eax, fs:[124h]
    6.         mov eax, [eax+130h]
    7.         mov pWinThread, eax
    8.     }
    9.     if (!pWinThread)
    10.     {
    11.         DbgPrint("--- NOT FOUND ACTIVE WIN32_THREAD ---\n");
    12.         return 0;
    13.     }
    14.     __asm{
    15.         mov edi, pWinThread
    16.         mov eax, [edi+0x30]
    17.         mov eax, [eax+0x28]
    18.         mov pWinThread, eax
    19.     }
    20.     if (!pWinThread)
    21.     {
    22.         DbgPrint("--- NOT FOUND ACTIVE WIN32_THREAD ---\n");
    23.         return 0;
    24.     }
    25.     __asm{
    26.         mov eax, pWinThread
    27.         mov esi, [eax]
    28.         mov eax, esi
    29.     }
    30. }
    Короче можно это найти через GetForegroundWindow брякнув Soft-Ice'ом, но там всплывает какой-то BF9A9940, значение в эту область попадает из csrss.exe. Если кто знает как с этим разобраться пожалуйста сообщите. По идеи где-то должно лежать текущее значение LCID в системе, но это не факт. Ход смены раскладки такой -> нажимаем сочетание клавиш -> система обрабатывает это нажатие получая scan code -> затем что-то меняет LCID текущего потока. Но вот что, и как это отследить?
     
  2. rav

    rav New Member

    Публикаций:
    0
    Регистрация:
    19 июл 2004
    Сообщения:
    159
    Адрес:
    Москва
    Посмотри на код оригинального GetKeyboardLayout в user32.dll- там всё написано! Ну а ты явно перемудрил...
     
  3. Guest

    Guest Guest

    Публикаций:
    0
    Повторяю я ничего не перемудрил :)
    DWORD GetKeyboardLayout(void) - Этот код взят из user32.dll и переписан для работы Ring-0. Попробуй поставить бряк на GetKeyboardLayout(DWORD idThread) и увидишь вызов KiFastSysCall из ntdll.dll, а далее идет путь в Ring-0, в котором устанавливается текущий поток или ищется поток с IdThread (если IdThread не ноль), из него берется структура Win32_thread, в которой лежит LCID (!), у каждого Win32 потока свой LCID, поробуй открыть несколько окон в проводнике и измени в одном раскладку - ты увидишь, что при переключении между окнами, раскладка запоминается, так вот она и хранится в потоке. Меня интересует как надежно получить текущую раскладку, т.к. при вызове GetKeyboardLayout нужно знать Id потока текущего активного окна, а как узнать текущее активное окно? функцией Get ForegroundWindow или GetActiveWindow (только свой поток, поэтому нам это не подходит). Сейчас копаюсь в GetForegroundWindow и чувствую что уже понял как работает эта хрень, поотом останется лишь найти Id потока этого окна, а по этому Id я найду этот поток и текущую активную раскладку. Вот если кто знает как все это можно сделать то сообщите, другие методы мало эффективны, т.к. драйвер должен работать самостоятельно, то есть интересует код работающий в Ring-0.
     
  4. dag

    dag New Member

    Публикаций:
    0
    Регистрация:
    17 авг 2004
    Сообщения:
    446
    EnumWindows ???
     
  5. rav

    rav New Member

    Публикаций:
    0
    Регистрация:
    19 июл 2004
    Сообщения:
    159
    Адрес:
    Москва
    Ещё раз- ты перемудрил. Вытащи ID функции, подставь в вызов int 2E- и будет тебе счастье. В противном случае ты затрахаешься с поддержкой совместимости.
     
  6. Guest

    Guest Guest

    Публикаций:
    0
    EnumWindows - не по теме будет, тут надо по другому делать. Насчет перемудрения - а ты это сам проверял и на чем? У меня как говорил XP SP2, я пробвал сделать такой вызов и в итоге BSOD. Во вторых такие функции легко перехватить и обнаружить. Использовать системные вызовы - не идеальный вариант - почитай статьи Ms-Rem'a и увидишь, что самый надежный способ - это все сделать самому и напрямую (PspCidTable - тому пример). Мне нужен максимально эффективный и необнаруживаемый способ.
     
  7. rav

    rav New Member

    Публикаций:
    0
    Регистрация:
    19 июл 2004
    Сообщения:
    159
    Адрес:
    Москва
    1. Можешь получать указатель на функцию в ядре но её ID и делать вызов.
    2. Я использую подобный метод (вызов по ID через int 2E) и не имею никаких проблем.
     
  8. Guest

    Guest Guest

    Публикаций:
    0
    Тут вообщем вот что получилось: Функция нужная мне - GetForegroundWindow вызывается из win32k.sys. В таблице SYSTEM_DESСRIPTION_TABLE можно вызвать функции только из ntoskrnl.exe, win32k.sys можно вызвать из теневой таблицы, ее сначала нужно найти (тут Касперский мешать будет, но это уже пройдено), чтобы сделать вызов (по словам Ms-Rem'a) нужно создать поток в User Mode процессе и контролировать его в драйвере. Короче слишком все запутано и сложно, работать это будет на 50%.
    Rav - если у тебя есть код рабочий под 2000/XP то скинь его на rapidshare.de и ссылку дай, надеюсь на твою помощь, а то нифига не пашет, неужели придется User Mode прогу к драйверу цеплять.
    P.S. Проверь только чтобы у тебя корректно работало (Функция должна быть с id > 1000, У меня GetForegroundWindow 1194h.). Кстати пробовал заюзать SYSENTER - VisualStudio его не понимает, пришлось в HIEW править, в итоге драйвер отказался запускаться - может нужны привелегии отладчика?
     
  9. khv_test

    khv_test New Member

    Публикаций:
    0
    Регистрация:
    30 июн 2004
    Сообщения:
    135
    2 im1111: если ты поправил драйвер не забудь про чек-сумму файлика а то не запуститься...
    а sysenter заменяй на __emit(0x0F);__emit(0x34);
     
  10. rav

    rav New Member

    Публикаций:
    0
    Регистрация:
    19 июл 2004
    Сообщения:
    159
    Адрес:
    Москва
    Код (Text):
    1. __declspec(naked) int ZwUserCallOneParam(ULONG ThreadId,ULONG Param){
    2.  
    3.     _asm{
    4.  
    5.         mov eax,[ZwUserCallOneParam_id]
    6.         lea edx,[esp][4]
    7.         int 0x2E
    8.         retn 2*4
    9.     }
    10.  
    11. }
    12.  
    13. HKL GetKeyboardLayout(ULONG ThreadId){
    14.  
    15.    if(*NtBuildNumber<2600) //(Win2k)
    16.        return ZwUserCallOneParam(ThreadId,0x1E);
    17.     else //(WinXP)
    18.        return ZwUserCallOneParam(ThreadId,0x28);
    19.  
    20. }
    ZwUserCallOneParam_id=1139 для 2000 и 1143 для XP. Можешь по ZwUserCallOneParam_id получить указатель на функцию и вызывать её напрямую, без использования int 2E переходника.
     
  11. Guest

    Guest Guest

    Публикаций:
    0
    Во вот так и надо работать. Спасибо большое за помощь в трудную минуту. А то я уже user mode прогу замутил для обновления информации о изменении раскладки по таймеру каждые 1/10 секунды - кстати отлично работает, но в теории ненадежно а значит будут сбои.
     
  12. k3internal

    k3internal New Member

    Публикаций:
    0
    Регистрация:
    11 янв 2007
    Сообщения:
    607
    Это для 2к я когда то сервис писал. Кароче там есть раздел, который ты можешь открыть и читать раскладку по определённому адресу.


    Код (Text):
    1. uses windows;
    2.  
    3. const
    4. IOCTL_KEYBOARD_QUERY_INDICATORS = $0B0040;
    5. IOCTL_KEYBOARD_SET_INDICATORS =   $0B0008;
    6.  
    7. KEYBOARD_NUM_LOCK_ON     = $2;
    8. KEYBOARD_CAPS_LOCK_ON    = $4;
    9. KEYBOARD_SCROLL_LOCK_ON  = $1;
    10.  
    11. type
    12. KEYBOARD_INDICATOR_PARAMETERS = record
    13.    UnitId:word;
    14.    LedFlags:word;
    15. end;
    16.  
    17. function DefineDosDeviceA(dwflags:dword;lpDeviceName:lpctstr;lpTargetPath:lpctstr):bool;
    18.          stdcall; external 'kernel32.dll';
    19.  
    20. var
    21.   KeybDeviceHandle: THandle;
    22.   kip:KEYBOARD_INDICATOR_PARAMETERS;
    23.   dwBytesReturned:DWORD;
    24.  
    25.   MH: THandle;
    26.   MapViewAddr: pointer;
    27.  
    28.   SI : Tstartupinfo;
    29.   PI : Tprocessinformation;
    30.  
    31.   LegFlags:cardinal;
    32.  
    33.   VI:OSVERSIONINFO;
    34.  
    35. /// _++_+_++__+_+_+_++_+_+  Попытка открытия раздела _+_+_+_+_+_
    36. function OpenMappedView:boolean;
    37. begin
    38. {$I-}    result:=False;
    39.          MapViewAddr:= nil;
    40.    MH:=CreateFileMapping($0FFFFFFFF,nil,4,0,$48,LPCTSTR('InternatSHData'));
    41.     if GetLastError = ERROR_ALREADY_EXISTS then
    42.        MapViewAddr:=MapViewOfFile(MH,2,0,0,0);
    43.        if MapViewAddr <> nil then result:=TRUE;
    44. {$I+}
    45. end;
    46. /// _+_+_+_++_+_++_+_+_+_+ считывание текущей раскладки _+_++_+_+_+_+_+
    47. function GetCurrentLayout:cardinal;
    48. begin
    49.     if MapViewAddr <> nil then begin
    50.        asm
    51.           pushad
    52.           mov eax,MapViewAddr
    53.           mov ebx,[eax+15*4]
    54.           and ebx,$0000FFFF
    55.           mov result,ebx
    56.           popad
    57.        end;
    58.         Sleep(200);
    59.     end else result:=0;
    60. end;
    61.  
    62. /// -=-==-=-=-==-=-=-=- включение светодиода клавиатуры _+_+_+_++_+_+_++
    63. procedure SetIndicator;
    64.   var
    65.      resultiocontrol:BOOL;
    66.      pkip:pointer;
    67.      label Lab_;
    68. begin
    69.      pkip:=@kip;
    70.  if DefineDosDeviceA(DDD_RAW_TARGET_PATH,LPCTSTR('KbdKBLayout'),LPCTSTR('\Device\KeyboardClass0'))
    71.     then begin
    72.     KeybDeviceHandle:=CreateFileA(LPCTSTR('\\.\KbdKBLayout'),0,0,nil,OPEN_EXISTING,0,0);
    73.      if KeybDeviceHandle <> THANDLE(-1)
    74.       then begin
    75.           ResultIOControl:=DeviceIOControl(KeybDeviceHandle,IOCTL_KEYBOARD_QUERY_INDICATORS,
    76.                     nil,0,pkip,sizeof(kip),dwBytesReturned,nil);
    77.                if (ResultIOControl <> FALSE) and (dwBytesReturned <> 0)
    78.                 then begin
    79.                         LegFlags:=kip.LedFlags;
    80.  
    81.                         kip.LedFlags:= KEYBOARD_NUM_LOCK_ON;
    82.                         DeviceIOControl(KeybDeviceHandle,IOCTL_KEYBOARD_SET_INDICATORS,
    83.                         pkip,sizeof(kip),nil,0,dwBytesReturned,nil);
    84.                         Sleep(100);
    85.                         kip.LedFlags:= KEYBOARD_CAPS_LOCK_ON;
    86.                         DeviceIOControl(KeybDeviceHandle,IOCTL_KEYBOARD_SET_INDICATORS,
    87.                         pkip,sizeof(kip),nil,0,dwBytesReturned,nil);
    88.                         Sleep(100);
    89.                         kip.LedFlags:= KEYBOARD_SCROLL_LOCK_ON;
    90.                         DeviceIOControl(KeybDeviceHandle,IOCTL_KEYBOARD_SET_INDICATORS,
    91.                         pkip,sizeof(kip),nil,0,dwBytesReturned,nil);
    92.                         Sleep(100);
    93.  
    94.                         kip.LedFlags:= KEYBOARD_CAPS_LOCK_ON;
    95.                         DeviceIOControl(KeybDeviceHandle,IOCTL_KEYBOARD_SET_INDICATORS,
    96.                         pkip,sizeof(kip),nil,0,dwBytesReturned,nil);
    97.                         Sleep(100);
    98.                         kip.LedFlags:= KEYBOARD_NUM_LOCK_ON;
    99.                         DeviceIOControl(KeybDeviceHandle,IOCTL_KEYBOARD_SET_INDICATORS,
    100.                         pkip,sizeof(kip),nil,0,dwBytesReturned,nil);
    101.                         Sleep(100);
    102.  
    103.                         kip.LedFlags:= LegFlags;
    104.                         DeviceIOControl(KeybDeviceHandle,IOCTL_KEYBOARD_SET_INDICATORS,
    105.                         pkip,sizeof(kip),nil,0,dwBytesReturned,nil);
    106.                         Sleep(100);
    107.  
    108.                         while OpenMappedView = FALSE do begin
    109.                                                         end;
    110.                 Lab_:
    111.                    if GetCurrentLayout = $419 then begin   // RU
    112.                         DeviceIOControl(KeybDeviceHandle,IOCTL_KEYBOARD_QUERY_INDICATORS,
    113.                         nil,0,pkip,sizeof(kip),dwBytesReturned,nil);
    114.                         kip.LedFlags:= kip.LedFlags or KEYBOARD_SCROLL_LOCK_ON;
    115.                         DeviceIOControl(KeybDeviceHandle,IOCTL_KEYBOARD_SET_INDICATORS,
    116.                         pkip,sizeof(kip),nil,0,dwBytesReturned,nil);
    117.                                           end else begin   // EN
    118.                         DeviceIOControl(KeybDeviceHandle,IOCTL_KEYBOARD_QUERY_INDICATORS,
    119.                         nil,0,pkip,sizeof(kip),dwBytesReturned,nil);
    120.                         kip.LedFlags:=kip.LedFlags and $FFFE ;
    121.                         DeviceIOControl(KeybDeviceHandle,IOCTL_KEYBOARD_SET_INDICATORS,
    122.                         pkip,sizeof(kip),nil,0,dwBytesReturned,nil);
    123.                                            end;
    124.                        goto Lab_;
    125.                   end;
    126.            end;
    127.          end;
    128. end;
    129.  
    130.  
    131.  
    132. /// _+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_
    133. begin
    134.        VI.dwOSVersionInfoSize:=SizeOf(Vi);
    135.        GetVersionEx(VI);
    136.        if VI.dwBuildNumber <> 2195 then begin
    137.        MessageBox(0,'For Windows 2000 Build 2195 only!','',MB_ICONINFORMATION);
    138.        ExitProcess(0);
    139.                                         end;
    140.        Createprocess(nil,'internat.exe',nil,nil,false,Create_default_error_mode,nil,nil,si,pI);
    141.        Sleep(10000);
    142.        SetIndicator;
    143. end.
     
  13. k3internal

    k3internal New Member

    Публикаций:
    0
    Регистрация:
    11 янв 2007
    Сообщения:
    607
    im1111
    Батенька, а контрольную сумму драйвера в этом случае пересчитывали ?
     
  14. k3internal

    k3internal New Member

    Публикаций:
    0
    Регистрация:
    11 янв 2007
    Сообщения:
    607
    khv_test
    Превед Вадик, как на пьянку соберёшса позвони, а то опять забудешь
     
  15. Guest

    Guest Guest

    Публикаций:
    0
    Не знаю что вы там курили но вы с этим завязывайте :))))) Тема создана в 2006 году :)
    А по теме: CRC не надо менять, HIEW править не придется есть emmit. А за код спасибо.
     
  16. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    Регистрация:
    24 ноя 2006
    Сообщения:
    5.582
    можно вообще ничего не делать - все равно sysenter в драйвере работать не будет. тогда уж int 2e ставить

    кстати зачот :))
     
  17. Guest

    Guest Guest

    Публикаций:
    0
    я сам офигел.
    Проблема уже давно решена, все работает.
     
  18. Miller Rabin

    Miller Rabin New Member

    Публикаций:
    0
    Регистрация:
    4 янв 2006
    Сообщения:
    185
    А можно подробнее насчет этого. Как это сделать?
     
  19. rain

    rain New Member

    Публикаций:
    0
    Регистрация:
    22 апр 2006
    Сообщения:
    976
    а что ж там делать? прочитать как диспетчеризируются ситемные вызовы, что такое KiServiceTable / W32pServiceTable можно где угодно хоть у руссиновича хоть у шрайбера, тока на х64 теперь там относительные смещения относительно самой таблици, а не асолютные, ничего тут сложного нет
     
  20. Miller Rabin

    Miller Rabin New Member

    Публикаций:
    0
    Регистрация:
    4 янв 2006
    Сообщения:
    185
    Вот же блин готовы удавиться за сколько-нибудь стоящую информацию.

    Вот пример поиска адреса ServiceDescriptorShadowTable
    http://www.volynkin.ru/sdts.htm