• XSS.stack #1 – первый литературный журнал от юзеров форума

Перенаправление ввода-вывода, Win32Api

one_deal

RAID-массив
Пользователь
Регистрация
14.12.2019
Сообщения
58
Реакции
5
Решил написать программу чтобы управлять cmd.exe не привлекая внимания санитаров.

Мне надо: запустить процесс, получить вывод.
Потом сделать ввод, затем считать вывод. и так постоянно.

Работа с Pipe из разряда научной фантастики.

С помощью CreateProcess запускаю cmd.exe с параметрами "cmd /c dir".
Код:
procedure StartExe(s: string); //Стартуем! В дорогу нам пора
var
  WaitThreadId: Cardinal;
  StartupInfo: TStartupInfo;
  SecurityAttributes: TSecurityAttributes;
  ProcessInformation: TProcessInformation;
begin
  Form1.Memo2.Lines.Add('Process started.');
  ZeroMemory(@SecurityAttributes, SizeOf(SecurityAttributes));
  SecurityAttributes.nLength := SizeOf(TSecurityAttributes);
  SecurityAttributes.lpSecurityDescriptor := nil;
  SecurityAttributes.bInheritHandle := True;
  CreatePipe(hPipeInputRead, hPipeInputWrite, @SecurityAttributes, 0);
  //SetHandleInformation(hPipeInputRead, HANDLE_FLAG_INHERIT, 0);
  CreatePipe(hPipeOutputRead, hPipeOutputWrite, @SecurityAttributes,
0);
  //SetHandleInformation(hPipeOutputRead, HANDLE_FLAG_INHERIT, 0);
  ZeroMemory(@StartupInfo, SizeOf(TStartupInfo));
  ZeroMemory(@ProcessInformation, SizeOf(TProcessInformation));
  StartupInfo.cb := SizeOf(TStartupInfo);
  StartupInfo.dwFlags := STARTF_USESHOWWINDOW or STARTF_USESTDHANDLES;
  StartupInfo.wShowWindow := SW_HIDE;
  StartupInfo.hStdInput := hPipeInputRead;
  StartupInfo.hStdOutput := hPipeOutputWrite;
  StartupInfo.hStdError := hPipeOutputWrite;
  if CreateProcess(nil, PChar(s), nil, nil, True, CREATE_NEW_CONSOLE,
nil, nil, StartupInfo, ProcessInformation) then
  begin
    hProcess := ProcessInformation.hProcess;
    hThread := CreateThread(nil, 0, @ReadThreadProc, nil, 0,
ThreadId);
  end;
end;
После запуска процесса в предыдущей функции на 30 строке я создаю с помощью
CreateThread поток ReadThreadProc
Код:
procedure ReadThreadProc;
var
  BytesCount: Cardinal;
  buf: array [0..4096] of Char;
begin
  Terminated := false;
  while not Terminated do
  begin
    if hPipeOutputRead <> INVALID_HANDLE_VALUE then
    begin
      ZeroMemory(@buf, SizeOf(buf));
      if ReadFile(hPipeOutputRead, buf, Length(buf), BytesCount, nil)
then
      begin
        if BytesCount <> 0 then
        begin
          //Вроде ошибка не здесь
          OemToAnsiBuff(buf, buf, BytesCount);
          Form1.Memo2.Text := Form1.Memo2.Text + Copy(buf, 1,
BytesCount);
        end;
      end;
    end;
  end;
end;
Здесь я считываю данные из PipeOutputRead и вывожу их в Memo.
<hr>
Время от времени я записываю данные в hPipeInputWrite:
Код:
procedure InputText(s: string);
var
  BytesCount: Cardinal;
  buf: array [0..4096] of Char;
begin
 //Проверяем размер вводимой строки:
  if Length(s) < 4090 then
  begin
    ZeroMemory(@buf, SizeOf(buf));
    StrPCopy(buf, s + #13#10); //
    WriteFile(hPipeInputWrite, buf, Length(s) + 2, BytesCount, nil);
  end;
end;
Иногда принудительно завершаю поток/процесс cmd.exe
Код:
procedure StopThread(); //Эта часть кода с глюками и часто вылетает
begin
  Terminated := true;

  if ThreadId <> INVALID_HANDLE_VALUE then
  begin
    WaitForSingleObject(ThreadId, INFINITE);
  end;
  if hThread <> INVALID_HANDLE_VALUE then CloseHandle(hThread);
  if hProcess <> INVALID_HANDLE_VALUE then
  begin
    TerminateProcess(hProcess, 255);
    WaitForSingleObject(hProcess, INFINITE);
    if hProcess <> INVALID_HANDLE_VALUE then CloseHandle(hProcess);
  end;
  if hPipeInputWrite <> INVALID_HANDLE_VALUE then CloseHandle
(hPipeInputWrite);
  if hPipeInputRead <> INVALID_HANDLE_VALUE then CloseHandle
(hPipeInputRead);
  if hPipeOutputWrite <> INVALID_HANDLE_VALUE then CloseHandle
(hPipeOutputWrite);
  if hPipeOutputRead <> INVALID_HANDLE_VALUE then CloseHandle
(hPipeOutputRead);
end;
Проблема в том, что при работе этого кода постоянно возникают ошибки:
Access Violation, External exception C0000008 и т.д.

Работа с Pipe из разряда научной фантастики.
Иногда работает иногда нет. Что я делаю не правильно?

Прочитал стотью с майкософт ком. ясности не привнесло
https://learn.microsoft.com/ru-ru/w...hild-process-with-redirected-input-and-output
 
Последнее редактирование:
Решил написать программу чтобы управлять cmd.exe не привлекая внимания санитаров.

Мне надо: запустить процесс, получить вывод.
Потом сделать ввод, затем считать вывод. и так постоянно.

Работа с Pipe из разряда научной фантастики.

С помощью CreateProcess запускаю cmd.exe с параметрами "cmd /c dir".
Код:
procedure StartExe(s: string); //Стартуем! В дорогу нам пора
var
  WaitThreadId: Cardinal;
  StartupInfo: TStartupInfo;
  SecurityAttributes: TSecurityAttributes;
  ProcessInformation: TProcessInformation;
begin
  Form1.Memo2.Lines.Add('Process started.');
  ZeroMemory(@SecurityAttributes, SizeOf(SecurityAttributes));
  SecurityAttributes.nLength := SizeOf(TSecurityAttributes);
  SecurityAttributes.lpSecurityDescriptor := nil;
  SecurityAttributes.bInheritHandle := True;
  CreatePipe(hPipeInputRead, hPipeInputWrite, @SecurityAttributes, 0);
  //SetHandleInformation(hPipeInputRead, HANDLE_FLAG_INHERIT, 0);
  CreatePipe(hPipeOutputRead, hPipeOutputWrite, @SecurityAttributes,
0);
  //SetHandleInformation(hPipeOutputRead, HANDLE_FLAG_INHERIT, 0);
  ZeroMemory(@StartupInfo, SizeOf(TStartupInfo));
  ZeroMemory(@ProcessInformation, SizeOf(TProcessInformation));
  StartupInfo.cb := SizeOf(TStartupInfo);
  StartupInfo.dwFlags := STARTF_USESHOWWINDOW or STARTF_USESTDHANDLES;
  StartupInfo.wShowWindow := SW_HIDE;
  StartupInfo.hStdInput := hPipeInputRead;
  StartupInfo.hStdOutput := hPipeOutputWrite;
  StartupInfo.hStdError := hPipeOutputWrite;
  if CreateProcess(nil, PChar(s), nil, nil, True, CREATE_NEW_CONSOLE,
nil, nil, StartupInfo, ProcessInformation) then
  begin
    hProcess := ProcessInformation.hProcess;
    hThread := CreateThread(nil, 0, @ReadThreadProc, nil, 0,
ThreadId);
  end;
end;
После запуска процесса в предыдущей функции на 30 строке я создаю с помощью
CreateThread поток ReadThreadProc
Код:
procedure ReadThreadProc;
var
  BytesCount: Cardinal;
  buf: array [0..4096] of Char;
begin
  Terminated := false;
  while not Terminated do
  begin
    if hPipeOutputRead <> INVALID_HANDLE_VALUE then
    begin
      ZeroMemory(@buf, SizeOf(buf));
      if ReadFile(hPipeOutputRead, buf, Length(buf), BytesCount, nil)
then
      begin
        if BytesCount <> 0 then
        begin
          //Вроде ошибка не здесь
          OemToAnsiBuff(buf, buf, BytesCount);
          Form1.Memo2.Text := Form1.Memo2.Text + Copy(buf, 1,
BytesCount);
        end;
      end;
    end;
  end;
end;
Здесь я считываю данные из PipeOutputRead и вывожу их в Memo.
<hr>
Время от времени я записываю данные в hPipeInputWrite:
Код:
procedure InputText(s: string);
var
  BytesCount: Cardinal;
  buf: array [0..4096] of Char;
begin
 //Проверяем размер вводимой строки:
  if Length(s) < 4090 then
  begin
    ZeroMemory(@buf, SizeOf(buf));
    StrPCopy(buf, s + #13#10); //
    WriteFile(hPipeInputWrite, buf, Length(s) + 2, BytesCount, nil);
  end;
end;
Иногда принудительно завершаю поток/процесс cmd.exe
Код:
procedure StopThread(); //Эта часть кода с глюками и часто вылетает
begin
  Terminated := true;

  if ThreadId <> INVALID_HANDLE_VALUE then
  begin
    WaitForSingleObject(ThreadId, INFINITE);
  end;
  if hThread <> INVALID_HANDLE_VALUE then CloseHandle(hThread);
  if hProcess <> INVALID_HANDLE_VALUE then
  begin
    TerminateProcess(hProcess, 255);
    WaitForSingleObject(hProcess, INFINITE);
    if hProcess <> INVALID_HANDLE_VALUE then CloseHandle(hProcess);
  end;
  if hPipeInputWrite <> INVALID_HANDLE_VALUE then CloseHandle
(hPipeInputWrite);
  if hPipeInputRead <> INVALID_HANDLE_VALUE then CloseHandle
(hPipeInputRead);
  if hPipeOutputWrite <> INVALID_HANDLE_VALUE then CloseHandle
(hPipeOutputWrite);
  if hPipeOutputRead <> INVALID_HANDLE_VALUE then CloseHandle
(hPipeOutputRead);
end;
Проблема в том, что при работе этого кода постоянно возникают ошибки:
Access Violation, External exception C0000008 и т.д.

Работа с Pipe из разряда научной фантастики.
Иногда работает иногда нет. Что я делаю не правильно?

Прочитал стотью с майкософт ком. ясности не привнесло
https://learn.microsoft.com/ru-ru/w...hild-process-with-redirected-input-and-output
Здравствуйте. Подскажите пожалуйста какой IDE Вы пользуетесь? Точнее чем компилируете. =)

Попробуйте компильнуть этим: https://www.lazarus-ide.org/

Если не получится, попробую вникнуть в Ваш код.

P. S. Из паскаля ушел давно, придется вспоминать по новой.
 
Последнее редактирование:
Погуглил тут, на Stackoverflow есть такой ответ, который вроде как помог:
Код:
C0000008 is the status returned for an invalid handle. Make sure that your wrapper when it goes to create the object gives it a proper handle and not nil (assuming it is crashing because of a windows handle).

Since the application runs fine when not attached to the debugger, I'm assuming that the wrapper is handling this condition gracefully so the error is most likely occurring inside a try/except block.

Используемая IDE у автора была: Borland Delphi 7

Увы, блоков try ... except в вашем коде не нашел.

Может попробовать добавить их и компильнуть?

 
Последнее редактирование:
Погуглил тут, на Stackoverflow есть такой ответ, который вроде как помог:
Код:
C0000008 is the status returned for an invalid handle. Make sure that your wrapper when it goes to create the object gives it a proper handle and not nil (assuming it is crashing because of a windows handle).

Since the application runs fine when not attached to the debugger, I'm assuming that the wrapper is handling this condition gracefully so the error is most likely occurring inside a try/except block.

Используемая IDE у автора была: Borland Delphi 7

Увы, блоков try ... except в вашем коде не нашел.

Может попробовать добавить их и компильнуть?

Среда delphi 7, дело не в среде. Пробовал ставить try/except, не помогло
 
Что-то с хендлами не так, мне дали такой совет, но пока не знаю как исправть. Вылетает до использования StopThread();

Попытка читать-писать закрытый хендл дает
c0000008. CloseHandle принимает значение - номер хендла, и закрывает
объект, на этом его полномочия все. Но в переменной у тебя остается
этот номер, он проходит проверку на !=-1 и дает тебе это исключение
попыткой залезть в эту трубу. Не давай программе лезть в закрытый
тобой хендл.
 
Пожалуйста, обратите внимание, что пользователь заблокирован
Возможно, хендлы не наследуются ? Это угадывание все. Советую сделать свой дочерний процесс, запускать его вместо цмд, аттачиться к нему и дебажить - смотреть,какие хендлы передаются.
 
Среда delphi 7, дело не в среде. Пробовал ставить try/except, не помогло
Отпишите завтра в ветку, если не справитесь, попытаюсь помочь.
 
Отпишите завтра в ветку, если не справитесь, попытаюсь помочь.
Посмотрел много проектов связанных с перенаправлением ввода-вывода, сравнил со своим кодом,
вроде все так же. Программа работает через раз и вызывает исключения при работе.

Изначально план был такой:
Взять несколько WinApi функций и собрать из них работающую прогу.
Если будут какие-то баги, найти их отладочным выводом.

Возникают исключения: Access Violation, External exception C0000008 при выполнении одних и тех же действий
 
Последнее редактирование:
Возможно, хендлы не наследуются ? Это угадывание все. Советую сделать свой дочерний процесс, запускать его вместо цмд, аттачиться к нему и дебажить - смотреть,какие хендлы передаются.
Не умею пользоваться отладчиком. Недавно начал смотреть видео с ютуб канала https://www.youtube.com/@yashechka85, до этого 10 лет пользовался отладочным выводом, здесь не могу осилить, ошибка другого плана
 
Последнее редактирование:
Внес коррективы в:

Код:
procedure ReadThreadProc;
var
  BytesCount, lpTotalBytesAvail: Cardinal;
  buf: array [0..4096] of Char;
begin
  Terminated := false;
  while not Terminated do
  begin
    if WaitForSingleObject(hProcess, 10) = WAIT_TIMEOUT then
    begin
      ZeroMemory(@buf, SizeOf(buf));
      if PeekNamedPipe(hPipeOutputRead, nil, 0, nil, @lpTotalBytesAvail, nil) then
      begin
        if lpTotalBytesAvail > 0 then
        begin
          if ReadFile(hPipeOutputRead, buf, Length(buf), BytesCount, nil) then
          begin
            if BytesCount <> 0 then
            begin
              OemToAnsiBuff(buf, buf, BytesCount);
              Form1.Memo2.Text := Form1.Memo2.Text + Copy(buf, 1, BytesCount);
            end;
          end;
        end;
      end;
    end;
  end;
end;

Добавил
Код:
if WaitForSingleObject(hProcess, 10) = WAIT_TIMEOUT then
и
Код:
      if PeekNamedPipe(hPipeOutputRead, nil, 0, nil, @lpTotalBytesAvail, nil) then

      begin

        if lpTotalBytesAvail > 0 then

Субьективно стало меньше исключений, но все таки вылетает, что не есть гуд
 
Последнее редактирование:
Исключение возникает при вводе текста:
Код:
procedure InputText(s: string);
var
  BytesCount: Cardinal;
  buf: array [0..4096] of Char;
begin
 //Проверяем размер вводимой строки:
  if Length(s) < 4090 then
  begin
    ZeroMemory(@buf, SizeOf(buf));
    StrPCopy(buf, s + #13#10); //
    WriteFile(hPipeInputWrite, buf, Length(s) + 2, BytesCount, nil);
  end;
end;
 
Так может освоишь мат-часть для начала? Ошибка может быть где угодно, особенно если это происходит через раз без закономерностей.
Мне такая мысль даже не приходила до твоего поста.
Заодно и асм с реверсингом освою ради одного проекта
 
Последнее редактирование:
Тему открыл после, как посмотрел другие решения в этой области и не смог найти ответ( в принципе по тексту это очевидно, если вы не идиот). Желающим самоутвердиться - оффтоп мне не интересен от слова совсем, энтропии без вас хватает
 
Последнее редактирование:
Возможно, хендлы не наследуются ?

У меня и там и там TRUE
  1. Создайте дескриптор с элементом bInheritHandle структуры SECURITY_ATTRIBUTES , который имеет значение TRUE.
  2. Создайте дочерний процесс с помощью функции CreateProcess с параметром bInheritHandles , равным TRUE.
 
Последнее редактирование:
Я тебе по делу ответил, запусти код, запусти отладчик и пройди по брэйкпоинтам, посмотри на какой строке крашится код и сюда отпиши, желательно прикрепи скрин. Как тебе помочь если ты банальные вещи не понимаешь и не хочешь понять?
https://xss.pro/threads/106279/#post-741570
 
На какой строке? Какой код ошибки? Что пишет отладчик? Скрин скинь.
Кроме этой строки, в этой функции, что-то еще может падать?
Код:
WriteFile(hPipeInputWrite, buf, Length(s) + 2, BytesCount, nil);

По твоему падает из за проверки длины статического буфера??
Или исключение возникает из за ZeroMemory статического буфера?
 
Последнее редактирование:
Создается один дочерний процесс, и джва отдельных пайпа
Код:
  CreatePipe(hPipeInputRead, hPipeInputWrite, @SecurityAttributes, 0);
  CreatePipe(hPipeOutputRead, hPipeOutputWrite, @SecurityAttributes, 0);

Скорее всего Access Violation, External exception C0000008 возникают из за
Код:
WriteFile(hPipeInputWrite, buf, Length(buf), BytesCount, nil);
Код:
ReadFile(hPipeOutputRead, buf, Length(buf), BytesCount, nil)

Кроме этого, не ясно из за чего еще могут возникать исключения
(еще вариант, что-то не так с хэндлами ведь exception C0000008),
хотя оне не закрываются/открываются во время выполнения
 
Последнее редактирование:
Пожалуйста, обратите внимание, что пользователь заблокирован
У меня и там и там TRUE
в коде может быть что угодно, любую вещь надо дебажить - т.е. запустить процесс, приаттачиться и посмотреть, какая именно апи в дочернем процессе дает такой эксепшн. И какие хендлы реально передаются.
 
в коде может быть что угодно, любую вещь надо дебажить - т.е. запустить процесс, приаттачиться и посмотреть, какая именно апи в дочернем процессе дает такой эксепшн. И какие хендлы реально передаются.
Пока весь дебаг в том что я запускаю свой ехе, и он вылетает в исключение.
Создал тему в надежде что кто-то из погромистов сталкивался с подобной проблемой.
 
Последнее редактирование:
Либо есть хорошие опесорсные решения в которых эта шляпа с пайпами нормально реализуется (це, ++)
 
Последнее редактирование:


Напишите ответ...
  • Вставить:
Прикрепить файлы
Верх