Оригинальный DVD-ROM: eXeL@B DVD !
eXeL@B ВИДЕОКУРС !

ВИДЕОКУРС ВЗЛОМ
выпущен 2 августа!


УЗНАТЬ БОЛЬШЕ >>
Домой | Статьи | RAR-cтатьи | FAQ | Форум | Скачать | Видеокурс
Новичку | Ссылки | Программирование | Интервью | Архив | Связь


<< ВЕРНУТЬСЯ В ПОДРАЗДЕЛ

<< ВЕРНУТЬСЯ В ОГЛАВЛЕНИЕ




Материалы находятся на сайте https://exelab.ru/pro/




ПРОГРАММИРОВАНИЕ НА C и С++



Возможности языков семейства Си по истине безграничны, однако, в этой свободе кроются и недостатки: всегда нужно программисту держать ухо востро и контроллировать "переполнение буфера", чтобы потом программа не вылетала в "синий экран" на массе разнообразных версий Windows и железа у пользователей. Те же крэкеры и реверсеры специально ищут в коде программ на Си уязвимости, куда можно подсадить любой вирусный код, об этом более подробно автор рассказывал в своём видеокурсе здесь. Я там многое узнал и теперь мой код стал значительно более безопасный.

Использование anonymous pipes для перехвата StdIn/StdOut дочернего процесса.

Автор: Borland Developer Support Staff
Перевод: Валерий Вотинцев

 

Тема:

О том, как создать дочерний процесс и передать управление его потоком ввода-вывода родительскому процессу за счет переадресации StdIn/StdOut.

 

Введение:

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

Неименованные пайпы используются для передачи данных только в одном направлении (только чтение или только запись). Зачем это может понадобиться? Для того, чтобы запустить какую-нибудь внешнюю утилиту и управлять ее поведением из своей программы. Например, это может быть телнет-сервер, который запускает DOS Shell и все, что выводится в шелле, передает через сокеты на удаленный хост.

Для начала мы поговорим о самих пайпах. Пайп в Windows - это просто один из методов коммуникации между процессами. В SDK дается следующее определение для пайпов: "пайп - это коммуникационный шлюз с двумя концами; некий процесс через дескриптор (handle) на одном конце пайпа может передавать данные другому процессу, находящемуся на другом конце пайпа."

В данном случае мы используем неименованные пайпы ("anonymous" pipes), т.е. однонаправленные пайпы, которые "передают данные между родительским и дочерним процессами или между двумя дочерними процессами одного и того же родительского процесса."
Образно говоря, пайп - это "труба", по которой между двумя процессами перетекают данные.

Для создания пайпа мы будем использовать функцию CreatePipe, которая вернет нам два дескриптора: дескриптор для записи и дескриптор для чтения.
Обратите внимание, что нам придется создать два пайпа: один для stdin и второй для stdout.

Далее мы будем следить за состоянием "читабельного конца" пайпа stdout для того, чтобы перехватить все, что будет там выведено, и отобразить в своем собственном окне.
Кроме того, мы будем проверять, введено ли что-нибудь в нашем приложении, и все, что введено, будем посылать в "записываемый конец" пайпа stdin.

 

Исходник:

 //------------Пример использования CreateProcess и Anonymous Pipes------
 
 // childspawn.cpp
 // Приложение запускает shell и перехватывает его ввод/вывод
 
 //---------------------use freely---------------------------------------
 
 #include <windows.h>
 #include <stdio.h>
 #include <conio.h>
 #include <string.h>
 #pragma hdrstop
 #include <condefs.h>
 
 
 
 #define bzero(a) memset(a,0,sizeof(a)) //для сокращения писанины
 
 
 
 bool IsWinNT()  //проверка запуска под NT
 {
   OSVERSIONINFO osv;
   osv.dwOSVersionInfoSize = sizeof(osv);
   GetVersionEx(&osv);
   return (osv.dwPlatformId == VER_PLATFORM_WIN32_NT);
 }
 
 
 
 void ErrorMessage(char *str)  //вывод подробной информации об ошибке
 {
 
   LPVOID msg;
 
   FormatMessage(
     FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
     NULL,
     GetLastError(),
     MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // язык по умолчанию
     (LPTSTR) &msg,
     0,
     NULL
   );
 
   printf("%s: %s\n",str,msg);
   LocalFree(msg);
 
 }
 
 
 
 //----------------------------------------------------------------------
 
 void main()
 
 {
 
   char buf[1024];           //буфер ввода/вывода
 
 
 
   STARTUPINFO si;
   SECURITY_ATTRIBUTES sa;
   SECURITY_DESCRIPTOR sd;        //структура security для пайпов
   PROCESS_INFORMATION pi;
 
   HANDLE newstdin,newstdout,read_stdout,write_stdin;  //дескрипторы
                                                       // пайпов
 
 
   if (IsWinNT())        //инициализация security для Windows NT
   {
     InitializeSecurityDescriptor(&sd,SECURITY_DESCRIPTOR_REVISION);
     SetSecurityDescriptorDacl(&sd, true, NULL, false);
     sa.lpSecurityDescriptor = &sd;
   }
 
   else sa.lpSecurityDescriptor = NULL;
 
   sa.nLength = sizeof(SECURITY_ATTRIBUTES);
   sa.bInheritHandle = true;       //разрешаем наследование дескрипторов
 
 
   if (!CreatePipe(&newstdin,&write_stdin,&sa,0))   //создаем пайп
                                                    // для stdin
   {
     ErrorMessage("CreatePipe");
     getch();
     return;
   }
 
   if (!CreatePipe(&read_stdout,&newstdout,&sa,0)) //создаем пайп
                                                   // для stdout
   {
     ErrorMessage("CreatePipe");
     getch();
     CloseHandle(newstdin);
     CloseHandle(write_stdin);
     return;
   }
 
 
 
   GetStartupInfo(&si);      //создаем startupinfo для
                             // дочернего процесса
 
   /*
 
   Параметр dwFlags сообщает функции CreateProcess
   как именно надо создать процесс.
 
   STARTF_USESTDHANDLES управляет полями hStd*.
   STARTF_USESHOWWINDOW управляет полем wShowWindow.
 
   */
 
   si.dwFlags = STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW;
   si.wShowWindow = SW_HIDE;
   si.hStdOutput = newstdout;
   si.hStdError = newstdout;   //подменяем дескрипторы для
   si.hStdInput = newstdin;    // дочернего процесса
 
   char app_spawn[] = "d:\\winnt\\system32\\cmd.exe"; //это просто
                                                      // пример,
                                                      //замените на то,
                                                      // что вам нужно
 
 
 
   //создаем дочерний процесс
 
   if (!CreateProcess(app_spawn,NULL,NULL,NULL,TRUE,CREATE_NEW_CONSOLE,
                      NULL,NULL,&si,&pi))
   {
     ErrorMessage("CreateProcess");
     getch();
     CloseHandle(newstdin);
     CloseHandle(newstdout);
     CloseHandle(read_stdout);
     CloseHandle(write_stdin);
     return;
   }
 
 
 
   unsigned long exit=0;  //код завершения процесса
   unsigned long bread;   //кол-во прочитанных байт
   unsigned long avail;   //кол-во доступных байт
 
 
 
   bzero(buf);
 
   for(;;)      //основной цикл программы
   {
     GetExitCodeProcess(pi.hProcess,&exit); //пока дочерний процесс
                                            // не закрыт
     if (exit != STILL_ACTIVE)
       break;
 
     PeekNamedPipe(read_stdout,buf,1023,&bread,&avail,NULL);
 
     //Проверяем, есть ли данные для чтения в stdout
 
     if (bread != 0)
     {
       bzero(buf);
       if (avail > 1023)
       {
         while (bread >= 1023)
         {
           ReadFile(read_stdout,buf,1023,&bread,NULL);  //читаем из
                                                        // пайпа stdout
           printf("%s",buf);
           bzero(buf);
         }
       }
 
       else {
         ReadFile(read_stdout,buf,1023,&bread,NULL);
         printf("%s",buf);
       }
     }
 
     if (kbhit())      //проверяем, введено ли что-нибудь с клавиатуры
     {
       bzero(buf);
       *buf = (char)getche();
 
       //printf("%c",*buf);
 
       WriteFile(write_stdin,buf,1,&bread,NULL); //отправляем это
                                                 // в stdin
 
       if (*buf == '\r') {
         *buf = '\n';
         printf("%c",*buf);
         WriteFile(write_stdin,buf,1,&bread,NULL); //формирум конец
                                                   //строки, если нужно
 
       }
     }
   }
 
   CloseHandle(pi.hThread);
   CloseHandle(pi.hProcess);
   CloseHandle(newstdin);            //небольшая уборка за собой
   CloseHandle(newstdout);
   CloseHandle(read_stdout);
   CloseHandle(write_stdin);
 }
 
 //----------------------------EOF-----------------------------------
 
 //------------------------------------------------------------------

 

 

Оригинальный DVD-ROM: eXeL@B DVD !


Вы находитесь на EXELAB.rU
Проект ReactOS