Blog. Just Blog

Получение данных из консольного окна другого приложения

Версия для печати Добавить в Избранное Отправить на E-Mail | Категория: Образ мышления: Assembler | Автор: ManHunter
Мы уже умеем перехватывать ввод и вывод консольных приложений, но этот способ работает только для тех процессов, которые мы сами запустили. Но иногда надо получать информацию из консольных приложений, которые уже были запущены в системе или могут быть запущены в дальнейшем, но не нами. А еще бывают консольные приложения, вывод которых невозможно перенаправить и, соответственно, невозможно получить описанным ранее способом. Для них также придется использовать способ из этой статьи.

Для начала как всегда несколько структур, которые изначально не описаны в FASM. Они нам понадобятся для работы с консольным окном:
  1. struct  COORD
  2.         X dw ?
  3.         Y dw ?
  4. ends
  5.  
  6. struct  SMALL_RECT
  7.         Left   dw ?
  8.         Top    dw ?
  9.         Right  dw ?
  10.         Bottom dw ?
  11. ends
  12.  
  13. struct CONSOLE_SCREEN_BUFFER_INFO
  14.         dwSize              COORD
  15.         dwCursorPosition    COORD
  16.         wAttributes         dw ?
  17.         srWindow            SMALL_RECT
  18.         dwMaximumWindowSize COORD
  19. ends
Теперь немного теории. Любое приложение, даже GUI, может создать собственную консоль или приаттачиться к уже существующей. Для аттача достаточно знать только идентификатор консольного процесса. После этого получаем стандартный хэндл вывода, используемый в этой консоли, параметры консольного окна (количество строк и столбцов), а потом единственной функцией ReadConsoleOutputCharacter забираем из консольного окна все содержимое.

Код достаточно простой, но несколько пояснений все-таки требуется. Зачем вызывать FreeConsole перед аттачем к консоли? Дело в том, что каждое приложение единовременно может работать только с одной консолью. При попытке подключиться к другой консоли, не разорвав связь с уже подключенной, система вернет ошибку. Функция FreeConsole разрывает связь с любой консолью, соединенной с вашим процессом. Даже если из своего кода вы никаких консолей пока не подключали, теоретически это могли сделать сторонние модули или внедренный код. Ситуация крайне маловероятная, но хорошим тоном будет ее предусмотреть.

При чтении данных из консольного окна вы можете забрать сразу все данные, но они будут переданы единой строкой без переносов. Для чтения построчно надо определить длину строки и выполнять последовательно чтение каждой строки, меняя начальные координаты позиции для чтения. Впрочем, если вам надо, например, просто узнать наличие каких-нибудь данных в консоли, то никто не запрещает читать ее единым куском. Финальные пробелы в строках не обрезаются, это также придется делать вашей программе.
  1.         ; Найти консольное окно
  2.         invoke  FindWindow,NULL,szTitle
  3.         or      eax,eax
  4.         jz      loc_exit
  5.  
  6.         ; Узнать ID процесса, связанного с консолью
  7.         invoke  GetWindowThreadProcessId,eax,pID
  8.  
  9.         ; Процесс может быть соединен только с одной консолью,
  10.         ; поэтому надо на всякий случай отсоединиться от
  11.         ; других консолей
  12.         invoke  FreeConsole
  13.  
  14.         ; Присоединиться к найденной консоли
  15.         invoke  AttachConsole,[pID]
  16.         or      eax,eax
  17.         jz      loc_exit
  18.  
  19.         ; Получить стандартный хэндл вывода
  20.         invoke  GetStdHandle,STD_OUTPUT_HANDLE
  21.         mov     [hOut],eax
  22.         ; Получить информацию об окне консоли
  23.         invoke  GetConsoleScreenBufferInfo,[hOut],csbi
  24.  
  25.         ; Счетчик строк
  26.         xor     eax,eax
  27.         ; Длина строки
  28.         movzx   ebx,[csbi.dwMaximumWindowSize.X]
  29. loc_read_y:
  30.         push    eax
  31.  
  32.         ; Координаты для чтения строки из консоли
  33.         mov     [grab.X],0
  34.         mov     [grab.Y],ax
  35.  
  36.         ; Прочитать строку из консоли
  37.         invoke  ReadConsoleOutputCharacter,[hOut],buff,ebx,[grab],tmp
  38.  
  39.         ; ...
  40.         ; Теперь в buff содержится строка из консольного окна
  41.         ; ...
  42.  
  43.         ; Следующая строка
  44.         pop     eax
  45.         inc     eax
  46.  
  47.         ; Все строки обработали?
  48.         cmp     ax,[csbi.dwMaximumWindowSize.Y]
  49.         jb      loc_read_y
  50.  
  51.         ; Отсоединиться от консоли
  52.         invoke  FreeConsole
  53.  
  54. loc_exit:
  55.         invoke  ExitProcess,0
Для удобства понимания здесь представлен только код для построчного чтения консоли, никаких действий с полученными данными не выполняется.

В приложении пример программы с исходным текстом, которая ищет консольное окно по заголовку (console_source.exe), получает из него все содержимое и выводит полученный текст в своем диалоговом окне.

Пример программы с исходным текстом (FASM)Пример программы с исходным текстом (FASM)

Grab.Console.Demo.zip (3,538 bytes)


Поделиться ссылкой ВКонтакте
Просмотров: 1863 | Комментариев: 0

Внимание! Статья опубликована больше года назад, информация могла устареть!

Комментарии

Отзывы посетителей сайта о статье
Комментариeв нет

Добавить комментарий

Заполните форму для добавления комментария
Имя*:
Текст комментария (не более 2000 символов)*:

*Все поля обязательны для заполнения.
Комментарии, содержащие рекламу, ненормативную лексику, оскорбления и т.п., а также флуд и сообщения не по теме, будут удаляться. Нарушителям может быть заблокирован доступ к сайту.
Наверх
Powered by PCL's Speckled Band Engine 0.2 RC3
© ManHunter / PCL, 2008-2024
При использовании материалов ссылка на сайт обязательна
Время генерации: 0.08 сек. / MySQL: 2 (0.0068 сек.) / Память: 4.5 Mb
Наверх