Blog. Just Blog

Управление редактором реестра из своего приложения

27.05.2020 | Категория: Образ мышления: Assembler | Автор: ManHunter
Наверняка вы слышали о программе RegJump от SysInternals, ныне принадлежащая Microsoft. При помощи этой программы вы можете открыть regedit сразу же на нужной ветке реестра. Мне стало очень интересно, как она это делает. Дизассемблер в руки, отладчик в боевую готовность и вперед!

Вот что мне удалось накопать. Я оставил только самый важный код, попутно упростив и оптимизировав его. Оригинальный RegJump сперва пытается найти запущенный regedit по наименованию класса окна, если такого нет, то пытается запустить regedit из системной папки. Так или иначе, вся работа выполняется с найденным окном. У меня подразумевается, что редактор реестра уже запущен.
  1. section '.data' data readable writeable
  2.  
  3. ; Классы окон для поиска
  4. szClass db 'RegEdit_RegEdit',0
  5. szList  db 'SysTreeView32',0
  6. ; Название ветки реестра
  7. szReg   db '\HKEY_LOCAL_MACHINE\SOFTWARE\MICROSOFT\WINDOWS\CURRENTVERSION\',0
Наименование ветки реестра, куда надо перейти, переводится в верхний регистр, а в начало и конец строки прицепляется символ "\". Традиционные сокращения типа "HKLM" разворачиваются в полноценные наименования веток реестра "HKEY_LOCAL_MACHINE" и т.п. Я надеюсь, с подобным преобразованием строки у вас проблем возникнуть не должно. У меня строка сразу приведена в должный вид.

Хэндл процесса необходим для синхронизации пользовательского ввода с окном приложения, поскольку все управление regedit выполняется через эмуляцию нажатий клавиш в списке. Для "своей" копии regedit, которая запущена RegJump, используется результат выполнения функции CreateProcess, для запущенного ранее экземпляра хэндл получается через пару функций GetWindowThreadProcessId и OpenProcess. Особых привилегий для этого не надо.
  1.         ; Найти окно редактора реестра
  2.         invoke  FindWindow,szClass,NULL
  3.         or      eax,eax
  4.         jz      loc_exit
  5.         mov     [hRWnd],eax
  6.  
  7.         ; Найти список в окне редактора реестра
  8.         invoke  FindWindowEx,[hRWnd],NULL,szList,NULL
  9.         or      eax,eax
  10.         jz      loc_exit
  11.         mov     [hWnd],eax
  12.  
  13.         ; Получить хэндл процесса-владельца
  14.         invoke  GetWindowThreadProcessId,[hRWnd],ProcessId
  15.         invoke  OpenProcess,PROCESS_QUERY_INFORMATION,0,[ProcessId]
  16.         or      eax,eax
  17.         jz      loc_exit
  18.         mov     [hProcess],eax
  19.  
  20.         ; Активировать окно редактора реестра
  21.         invoke  ShowWindow,[hRWnd],SW_RESTORE
  22.         invoke  SetForegroundWindow,[hRWnd]
  23.         ; Установить фокус на список
  24.         invoke  SetFocus,[hWnd]
  25.         invoke  WaitForInputIdle,[hProcess],-1
  26.  
  27.         ; Вот тут непонятно :(
  28.         invoke  SendMessage,[hRWnd],WM_COMMAND,10288h,0
  29.         invoke  WaitForInputIdle,[hProcess],-1
  30.  
  31.         ; Перейти на верхний уровень списка
  32.         mov     ebx,30
  33. @@:
  34.         invoke  SendMessage,[hWnd],WM_KEYDOWN,VK_LEFT,0
  35.         invoke  WaitForInputIdle,[hProcess],-1
  36.         sub     ebx,1
  37.         jnz     @b
  38.  
  39.         ; Указатель на строку в названием ветки реестра
  40.         mov     esi,szReg
  41. loc_loop:
  42.         lodsb
  43.         or      al,al
  44.         jz      loc_exit_clean
  45.  
  46.         cmp     al,'\'
  47.         jne     @f
  48.         ; Открыть ветку списка
  49.         invoke  SendMessage,[hWnd],WM_KEYDOWN,VK_RIGHT,0
  50.         invoke  WaitForInputIdle,[hProcess],-1
  51.         jmp     loc_loop
  52. @@:
  53.         movzx   eax,al
  54.         ; Поиск строки в списке
  55.         invoke  SendMessage,[hWnd],WM_CHAR,eax,0
  56.         invoke  WaitForInputIdle,[hProcess],-1
  57.         jmp     loc_loop
  58. loc_exit_clean:
  59.         invoke  CloseHandle,[hProcess]
  60.  
  61. loc_exit:
Когда все нужные окна найдены и хэндл процесса получен, начинается эмуляция нажатий клавиш. Сперва выполняется переход на самый верхний уровень списка. Судя по коду, Марк Руссинович предположил, что глубже 30-го уровня списка зайти невозможно, что ж, ему виднее. Затем начинается обработка строки с нужным названием ветки реестра. Строка обрабатывается посимвольно, когда встретится символ "\", то эмулируется нажатие стрелки вправо для открытия нужного уровня списка и перехода на него. Именно для этого исходная строка дополняется в начале и в конце этим символом. Строковые символы из строки передаются в поиск, тем самым определяя следующий уровень списка. Как видите, никаких ракетных технологий, но лично мне было очень интересно посмотреть на решение этой задачи от одного из признанных знатоков внутренностей Windows.

Читать статью целиком »
Просмотров: 1573 | Комментариев: 6

Наверх
Powered by PCL's Speckled Band Engine 0.2 RC3
© ManHunter / PCL, 2008-2024
При использовании материалов ссылка на сайт обязательна
Время генерации: 0.1 сек. / MySQL: 1 (0.0179 сек.) / Память: 4.5 Mb
Наверх