Blog. Just Blog

Запуск процессов с командой перенаправления вывода

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

tree c:\windows > out.txt
В этом случае вывод команды tree вполне ожидаемо будет сохранен в файл out.txt. Но если попытаться выполнить эту же команду средствами WinAPI, например, через функции WinExec, CreateProcess или ShellExecute(Ex), то нужного результата достигнуто не будет. Дело в том, что перенаправление обрабатывается только командным процессором, а функции WinAPI просто передают командную строку в неизменном виде, то есть программе "tree" будут переданы параметры "c:\windows > out.txt". В большинстве случаев они окажутся просто некорректными с точки зрения программы, а могут привести к неожиданным результатам.
  1.         ; Выполнить напрямую команду с перенаправлением
  2.         invoke  WinExec,exec_re,SW_SHOW
  3.         ...
  4.         ...
  5. exec_re  db 'c:\Windows\System32\tree.com c:\Windows\System32 >out.txt',0
Приведенный выше код выполнится без ошибок (имеется в виду код возврата WinExec), но при этом никакого файла с листингом создано не будет.

Если вы хотите, чтобы эти символы интерпретировались в вашем приложении как операторы перенаправления вывода, то вам нужно передавать их командному процессору следующим образом:

cmd.exe /c tree c:\windows > out.txt
Хорошим тоном будет сперва узнать, где в системе обитает командный процессор. Сделать это можно, получив значение переменной окружения COMSPEC.
  1.         ; Получить переменную окружения COMSPEC
  2.         ; со ссылкой на командный процессор
  3.         invoke  GetEnvironmentVariable,variable,cmd,100h
  4.         ; Дописать ключ /c
  5.         invoke  lstrcat,cmd,exec_add
  6.         ; Дописать выполняемую команду с перенаправлением
  7.         invoke  lstrcat,cmd,exec_re
  8.         ; Выполнить команду через командный процессор
  9.         invoke  WinExec,cmd,SW_SHOW
  10.         ...
  11.         ...
  12. exec_re  db 'c:\Windows\System32\tree.com c:\Windows\System32 >out.txt',0
  13. exec_add db ' /c ',0
  14. variable db 'COMSPEC',0
Для перенаправления вывода консольной программы можно использовать подход, описанный в статье "Перехват ввода и вывода консольных программ". Суть метода заключается в следующем: сначала создается файл с помощью функции CreateFile, при этом в структуре SECURITY_ATTRIBUTES поле bInheritHandle устанавливается в значение TRUE. Это позволяет дочернему процессу унаследовать хэндл файла. Далее заполняется структура STARTUPINFO, ее поле dwFlags устанавливается флаг STARTF_USESTDHANDLES, а в поля hStdOutput и hStdError записывается хэндл ранее созданного файла. Важно отметить, что именно флаг STARTF_USESTDHANDLES заставляет систему учитывать значения hStdOutput и hStdError, без него эти поля игнорируются независимо от настроек наследования. Затем вызывается функция CreateProcess с параметром bInheritHandles, установленным в TRUE. Этот параметр разрешает процессу наследовать все хэндлы, помеченные как наследуемые через SECURITY_ATTRIBUTES. В результате вывод и ошибки запущенной консольной программы направляются напрямую в файл, минуя командный процессор cmd.exe.
  1.         ; Заполнить структуру SECURITY_ATTRIBUTES
  2.         mov     [sattr.nLength],sizeof.SECURITY_ATTRIBUTES
  3.         mov     [sattr.lpSecurityDescriptor],0
  4.         mov     [sattr.bInheritHandle],TRUE
  5.  
  6.         ; Создание выходного файла с наследуемыми атрибутами
  7.         invoke  CreateFile,filen,GENERIC_WRITE,\
  8.                 0,sattr,CREATE_ALWAYS,\
  9.                 FILE_ATTRIBUTE_NORMAL,0
  10.  
  11.         ; Проверка
  12.         mov     ebx,eax
  13.         cmp     eax,INVALID_HANDLE_VALUE
  14.         je      .loc_error
  15.  
  16.         ; Заполнить структуру STARTUPINFO данными процесса
  17.         mov     [sinfo.cb],sizeof.STARTUPINFO
  18.         mov     [sinfo.dwFlags],STARTF_USESTDHANDLES
  19.         mov     [sinfo.hStdInput],0
  20.         mov     [sinfo.hStdOutput],ebx
  21.         mov     [sinfo.hStdError],ebx
  22.  
  23.         ; Запустить консольное приложение
  24.         invoke  CreateProcess,exec_pt,exec_cl,\
  25.                 0,0,TRUE,CREATE_NO_WINDOW,0,0,sinfo,pinfo
  26.  
  27.         test    eax,eax
  28.         jz      .loc_error
  29.  
  30.         ; Синхронное ожидание завершения tree.com
  31.         invoke  WaitForSingleObject,[pinfo.hProcess],\
  32.                 INFINITE
  33.  
  34.         ; Прибраться за собой
  35.         invoke  CloseHandle,[pinfo.hProcess]
  36.         invoke  CloseHandle,[pinfo.hThread]
  37.         ; Закрыть файл
  38.         invoke  CloseHandle,ebx
  39.  
  40.         invoke  ExitProcess,0
  41.  
  42. .loc_error:
  43.         ; Прибраться за собой
  44.         invoke  CloseHandle,ebx
  45.         invoke  ExitProcess,1
В приложении пример программы с исходным текстом, которая отрабатывает запуск приложения различными способами с перенаправлением вывода.

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

Input.Output.Redirection.Demo.zip (3,420 bytes)


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

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

Комментарии

Отзывы посетителей сайта о статье
ManHunter (03.02.2026 в 16:24):
Добавил способом перенаправления с CreateFile + CreateProcess. Спасибо, пригодится. Архив обновлен.
Илья (21.01.2026 в 20:15):
Можно сделать технологичнее и без запуска cmd.

Через функцию CreateProcessW с установкой параметра bInheritHandles и передачей в поле hStdOutput структуры STARTUPINFOW предварительно открытого наследуемого дескриптора файла.
dma (09.07.2019 в 11:05):
Ну еще бы ManHunter, да оказался бы не прав - прав конечно. Человек который не скрывает ни своего лица, ни страны, ни города проживания, ни горячих точек (или точки), в котороых(ой) ему довелось побывать - не может быть не правым. И самое интересное, что всем этим можно гордиться.

На меня, видимо, произвела впечатление эта тема, потому что я недавно интересовался ей, а эта ветка явилась как бы приятным бонусом к моим знаниям. Как говорится, кто предупрежден - тот вооружен. Вдруг когда-нибудь буду заниматься плотно этой темой и всплывет подобная проблема.
ManHunter (09.07.2019 в 09:51):
Это нормально. Кому-то нравится попадья, а кому-то свиной хрящик.
dma (09.07.2019 в 09:46):
ManHunter, немного не хватает вашему блогу равномерности интересов среди ваших читателей. В каких-то ветках число комментариев порой зашкаливает за сотню, а здесь ни одного. Я решил хоть как-то исправить эту несправедливость. Но вы ж понимаете, мои возможности, к сожалению (а может и к счастью :)), достаточно скромны, а так бы я с радостью организовал бы здесь сто положительных отзывов. Видимо люди не слышали о таком понятии как шеллкод, а эта ветка как бы предподготовка к нему. Я правильно мыслю или нет? :) К чему это я? К спасибе, естественно, а к чему еще. :)

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

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

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