Страницы

Поиск по вопросам

четверг, 5 декабря 2019 г.

Считать данные из CMD

#c_sharp #net #visual_studio


Добрый день, у меня вопрос, есть ли возможность считывания данных из командной строки
без использования 

RedirectStandardError = true;
RedirectStandardInput = true;
RedirectStandardOutput = true;


ибо в такой ситуации не доступна пользовательская оболочка.
Задача определить определено состояние соединения при старте путем считывания вывода

ValueCommandLine.StatusRunTelnet = true;
CommandLine.BasicMethods.MaxWindowsTelnet();
ProcessStartInfo Info = new ProcessStartInfo();
Info.Arguments = WCF_Client.ValueCommandLine.IP;
Info.FileName = "telnet.exe";
Info.UseShellExecute = true;
Info.CreateNoWindow = false;
Info.WindowStyle = ProcessWindowStyle.Minimized;
Process pTelnet = new Process();
pTelnet.StartInfo = Info;
pTelnet.Start();


но с возможностью дальнейшие работы пользователя с данным приложением 
    


Ответы

Ответ 1



Как я понимаю, вам нужно получить оутпут при работе с телнетом. Мне кажется вы пытаетесь решить данную задачу не верным путем. Telnet, это протокол, а раз это протокол, то вы в принципе можете сами реализовать с ним общение, а значит и получать оутпут как вам угодно. Например вот так: // создание подключение где hostname: имя хоста, 23 - номер порта TelnetConnection tc = new TelnetConnection("hostname", 23); // логин, с 100мс таймаутом string s = tc.Login("root", "rootpassword",100); // показываем оутпут Console.Write(s); // оуптут должен оканчиваться $ или > иначе ошибка подключения string prompt = s.TrimEnd(); prompt = s.Substring(prompt.Length -1,1); if (prompt != "$" && prompt != ">" ) throw new Exception("Connection failed"); prompt = ""; // цикл обработки подключения while (tc.IsConnected && prompt.Trim() != "exit" ) { // отображение оутпута Console.Write(tc.Read()); // отправка команды на сервер prompt = Console.ReadLine(); tc.WriteLine(prompt); // отображение ответа сервера Console.Write(tc.Read()); } Console.WriteLine("***DISCONNECTED"); Console.ReadLine(); Код клиента: using System; using System.Collections.Generic; using System.Text; using System.Net.Sockets; namespace MinimalisticTelnet { enum Verbs { WILL = 251, WONT = 252, DO = 253, DONT = 254, IAC = 255 } enum Options { SGA = 3 } class TelnetConnection { TcpClient tcpSocket; int TimeOutMs = 100; public TelnetConnection(string Hostname, int Port) { tcpSocket = new TcpClient(Hostname, Port); } public string Login(string Username,string Password,int LoginTimeOutMs) { int oldTimeOutMs = TimeOutMs; TimeOutMs = LoginTimeOutMs; string s = Read(); if (!s.TrimEnd().EndsWith(":")) throw new Exception("Failed to connect : no login prompt"); WriteLine(Username); s += Read(); if (!s.TrimEnd().EndsWith(":")) throw new Exception("Failed to connect : no password prompt"); WriteLine(Password); s += Read(); TimeOutMs = oldTimeOutMs; return s; } public void WriteLine(string cmd) { Write(cmd + "\n"); } public void Write(string cmd) { if (!tcpSocket.Connected) return; byte[] buf = System.Text.ASCIIEncoding.ASCII.GetBytes(cmd.Replace("\0xFF","\0xFF\0xFF")); tcpSocket.GetStream().Write(buf, 0, buf.Length); } public string Read() { if (!tcpSocket.Connected) return null; StringBuilder sb=new StringBuilder(); do { ParseTelnet(sb); System.Threading.Thread.Sleep(TimeOutMs); } while (tcpSocket.Available > 0); return sb.ToString(); } public bool IsConnected { get { return tcpSocket.Connected; } } void ParseTelnet(StringBuilder sb) { while (tcpSocket.Available > 0) { int input = tcpSocket.GetStream().ReadByte(); switch (input) { case -1 : break; case (int)Verbs.IAC: // interpret as command int inputverb = tcpSocket.GetStream().ReadByte(); if (inputverb == -1) break; switch (inputverb) { case (int)Verbs.IAC: //literal IAC = 255 escaped, so append char 255 to string sb.Append(inputverb); break; case (int)Verbs.DO: case (int)Verbs.DONT: case (int)Verbs.WILL: case (int)Verbs.WONT: // reply to all commands with "WONT", unless it is SGA (suppres go ahead) int inputoption = tcpSocket.GetStream().ReadByte(); if (inputoption == -1) break; tcpSocket.GetStream().WriteByte((byte)Verbs.IAC); if (inputoption == (int)Options.SGA ) tcpSocket.GetStream().WriteByte(inputverb == (int)Verbs.DO ? (byte)Verbs.WILL:(byte)Verbs.DO); else tcpSocket.GetStream().WriteByte(inputverb == (int)Verbs.DO ? (byte)Verbs.WONT : (byte)Verbs.DONT); tcpSocket.GetStream().WriteByte((byte)inputoption); break; default: break; } break; default: sb.Append( (char)input ); break; } } } } }

Ответ 2



Задачу можно попробовать решить хакерским способом. Гарантии не даю потому как не проверял. В исходном процессе делаем следующее: Создаем именованый глобальный блок памяти с заранее известным именем, например RobData. Размер это блока должен быть минимум 12 байтов: 4 байта для PID`а исходного процесса и 8 байтов для хендла потока. Пишем в этот блок PID исходного процесса. Создаем объект именованного события также с заранее изветсным именем, например RobNotify. С помощью внедрения DLL подмапываем предварительно подготовленную хитрую DLL (о ней ниже). Ждем наступления события RobNotify Вычитываем хендл пайпа стандартного потока и пользуем его как обычно, но не забываем что пайп состоит из двух хендлов и у нас в распоряжении хендл для отправляющей стороны. В хитрой DLL в DllMain по DLL_PROCCESS_ATTACH должно быть примерно следующее: BOOL APIENTRY DllMain(HMODULE, DWORD reason, LPVOID) { switch(reason) { case DLL_PROCESS_ATTACH: { STARTUPINFO info = {0}; GetStartupInfo(&info); DWORD target_pid = 0; // открываем блок памяти "RobData" (сопсобом из п. 1) // и вычитываем из него PID исходного процесса в target_pid HANDLE target_process = OpenProcess(PROCESS_ALL_ACCESS, FALSE, target_pid); HANDLE target_pipe ; DublicateHandle // клонируем хендл пайпа в исходный процесс ( GetCurrentProcess() , info.hStdOutput // хендл пайпа для стандартного вывода , target_process , &target_pipe , 0 , TRUE , DUPLICATE_SAME_ACCESS ); // записываем клонированный target_pipe в "RobData" HANDLE notify = OpenEvent(EVENT_ALL_ACCESS, FALSE, _T("SpyNotify")); SetEvent(notify); CloseHandle(notify); CloseHandle(target_process); // закрываем глобальную память "RobData" } break; // обрабатываем другие события } return TRUE; } Да, и еще нужно решить все вопросы с правами доступа - их там много. Вполне допускаю что пайп стандартного потока какой-нибудь шибко закалдованный и клонированию не поддается или с правами засада, вообщем проверять надо.

Комментариев нет:

Отправить комментарий