netcat mit c++ bedienen



  • okay, dann werde ich das mal probieren. vielen dank 🙂 ich guck mir das alles mal genauer an und versuhch die einzelnen schritte zu vertsehen



  • müsste ich, soweit ich das verstanden hab, dann im endeffekt zwei pipes haben. also pipe.h und pipe2.h zB. eben einmal für die umleitung der eingabgeströme eins und eins für die ausgabeströme?



  • Zwei Pipes ja, aber nicht pipe1.h und pipe2.h ...
    Probier mal folgendes(pipe.h und pipe.cpp bleiben wie gehabt):
    Das hab ich jetzt nur mal auf die Schnelle so hingerotzt, aber für das Testprogramm funktioniert es:

    #ifndef MYCONSOLEH
    #define MYCONSOLEH
    
    #include <string>
    #include "pipe.h"
    
    class myConsole
    {
    	public:
    		myConsole();
    		void doCommand(std::string command);
    		std::string readFromProcess();
    
    	private:
    
    		pipe writePipe;
    		pipe readPipe;
    
    		void startCommandProcess(HANDLE wrHandle, HANDLE rdHandle);
    };
    
    #endif
    
    #include <iostream>
    #include "myConsole.h"
    
    //public
    
    myConsole::myConsole()
    {
    	writePipe.MakeInheritable(pipe::READ);
    	readPipe.MakeInheritable(pipe::WRITE);
    
    	startCommandProcess(readPipe.GetPipeHandle(pipe::WRITE), writePipe.GetPipeHandle(pipe::READ));
    
    	writePipe.ClosePipeHandle(pipe::READ);
    	readPipe.ClosePipeHandle(pipe::WRITE);
    
    }
    
    void myConsole::doCommand(std::string command)
    {
    	DWORD ignore;
    
    	command.append("\n");
    	WriteFile(writePipe.GetPipeHandle(pipe::WRITE), command.c_str(), command.size(), &ignore, 0);
    }
    
    std::string myConsole::readFromProcess()
    {
       char inBuf[256];
       DWORD nBytesRead = 0;
    	std::string tmp;
    
    	ReadFile(readPipe.GetPipeHandle(pipe::READ), inBuf, 256, &nBytesRead, NULL);
    	return std::string(inBuf, nBytesRead);
    
    /*
       while(TRUE)
       {
          if (!ReadFile(readPipe.GetPipeHandle(pipe::READ), inBuf, 256, &nBytesRead, NULL) || !nBytesRead)
          	break;
    
          for(int i = 0; i < nBytesRead; ++i)
          {
          	if(inBuf[i] == 10)
          	{
          		result.push_back(tmp);
          		tmp.clear();
          	}
          	else if(inBuf[i] == 13)
          		;
          	else
          		tmp.push_back(inBuf[i]);
          }
       }	
    */
    }
    
    //private
    void myConsole::startCommandProcess(HANDLE wrHandle, HANDLE rdHandle)
    {
       PROCESS_INFORMATION pi;
       STARTUPINFO si;
    
       // Set up the start up info struct.
       ZeroMemory(&si,sizeof(STARTUPINFO));
       si.cb = sizeof(STARTUPINFO);
       si.dwFlags = STARTF_USESTDHANDLES;
       si.hStdInput = rdHandle;
       si.hStdOutput = wrHandle;
       si.hStdError  = wrHandle;
    
       // Use this if you want to hide the child:
       //   si.wShowWindow = SW_HIDE;
       // Note that dwFlags must include STARTF_USESHOWWINDOW if you want to
       // use the wShowWindow flags.
    
       // Launch the process that you want to redirect (in this case,
       // Child.exe). Make sure Child.exe is in the same directory as
       // redirect.c launch redirect from a command line to prevent location
       // confusion.
    
       CreateProcess(NULL, "cmd", NULL, NULL, TRUE, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi);
    
       // Close any unnecessary handles.
       CloseHandle(pi.hThread);
       CloseHandle(pi.hProcess);
    }
    

    Testprogramm:

    #include <iostream>
    #include <string>
    #include "myConsole.h"
    
    using namespace std;
    
    int main()
    {
    	myConsole mc;
    
    	//einige Kommandos absetzen, bei Dir zB "netcat ..." usw.
    	mc.doCommand("dir");
    	mc.doCommand("ipconfig");
    	mc.doCommand("attrib");
    
    	//Ab hier die Ausgaben lesen und verarbeiten, hier werden sie einfach 
    	//via cout auf die Konsole geschrieben
    	string str;
    	do
    	{
    		str = mc.readFromProcess();
    
    		cout << str;
    	}while(str.size());
    }
    

    Edit:
    Nachteil bei dieser threadlosen Lösung ist, wenn der gestartet Prozess nichts mehr schreibt, bleibt das Programm in readFromProcess hängen.



  • Ich verstehe diese ganze Diskussion nicht. Die Lösung ist doch viel einfacher. Sie wurde hier auch schon erwähnt: einfach die Socket-API verwenden.

    Netcat dient dazu, Daten über eine TCP-Verbindung zu schicken. Dazu gibt es eben die Socket-API. Da ich aber auf der Kommandozeile die API nicht direkt ansprechen kann, gibt es dieses Kommandozeilentool. Da ich in einem C++-Programm die API direkt ansprechen kann, macht es keinen Sinn, das Kommandozeilentool zu verwenden.

    Prinzipiell sollte man im C++-Programmen wo immer möglich die API verwenden. Ein Kommandozeilentool aus einem C++-Programm aufzurufen, macht in den wenigsten Fällen Sinn.

    Das gilt nicht nur für netcat sondern auch für die verwendeten Beispiele "dir", "ipconfig" oder "attrib".



  • vielen dank belli erstmal für den code, ich werde dsa ausporbieren sobald ich zeit habe

    @ ich bins:
    wie würde das denn mit dem ansprechen der api aussehen?



  • Es sieht noch immer so aus wie ich es auch schon am 11.05. hier gepostet habe^^:

    Du könntest das ganze auch mit WIN Sock machen und ganz auf Netcat verzichten.

    http://msdn.microsoft.com/en-us/library/windows/desktop/ms738545(v=vs.85).aspx (Englisch)

    Und da ich ebenfalls der Held von Google bin habe ich noch mehr Links für dich.

    http://www.c-worker.ch/tuts.php (Deutsch, is aber C und kein C++ aber ist leich in C++ umzuändern. )

    http://www.madwizard.org/programming/tutorials/netcpp/ (Englisch )( Auf der Seite nach ganz unten Scrollen und rechts steht dann "Networking introduction" und ab da gehts weiter. )



  • jasdefer schrieb:

    vielen dank belli erstmal für den code, ich werde dsa ausporbieren sobald ich zeit habe

    @ ich bins:
    wie würde das denn mit dem ansprechen der api aussehen?

    Die Links von "Held vom MSDN !" beschreiben genau das. Und es gibt noch etliche andere Seiten, wo die Netzwerkprogrammierung erklärt wird.



  • Okay danke, ich gucke mir das noch einmal an. wenn das ganze einfacher als mit netcat ist, warum nicht^^

    habe allerdings eine frage, ich benutzt dev-c++ als compiler und finde nirgends wie man folgenden punkte dort einstellen kann:

    Ensure that the build environment refers to the Include, Lib, and Src directories of the Microsoft Windows Software Development Kit (SDK) or the earlier Platform Software Development Kit (SDK).

    für visual hab ich was gefunden, allerdings nicht für dev-c++. wisst ihr wie man das hier macht?



  • @Belli:
    Vielen Dank für deinen hingerotzen code 😃 auch wenn die anderen sagen es wäre umständlich^^ egal. es scheint zu funktionieren. vielen dank dafür^^ ich gucke es mir weiter an.

    Mit winsocket wäre es vllt noch etwas cooler, aber für mich jetzt viel mehr aufwand^^, falls das hier nicht funktionieren sollte, werde ich mir das mit winsocket nochmal angucken. euch auch vielen dank 🙂



  • Vielleicht ist es cooler mit Sockets ... aber wenn man da erst noch lernen muss, wie es funktioniert, ist das schon ein recht hoher Aufwand. Hinzu kommt, dass Du evtl. ja gar nicht weißt, was Dein netcat alles kann, und was Du dementsprechend alles nachprogrammieren musst.
    Im übrigen hindert Dich ja niemand, das später noch nachzuholen oder zu versuchen. Die hier geposteten Klassen dienen erst mal dazu, auf einfache Weise jedes mögliche Programm, was sich über STDIN steuern lässt, anzusprechen und sind so in gewisser Weise universell einsetzbar.
    Klar kann ich via WINAPI ein dir auch programmieren. Aber wenn ich die verschiedenen Optionen, die dir kann, alle nachbilden will, ist das auch eine Menge Arbeit.
    Wenn das so für Dich erst mal funktioniert, freu ich mich, Dir geholfen zu haben!



  • ich habe nochmal einiges probiert, allerdings gibt es noch ein problem. also dass die ausgabe der konsole in dem string gespeichert wird ist super und funktioniert eigentlich. ich öffne netcat, dann zeigt er mir bei der ausgabe auch an netcat geöffnet etc. allerdings wenn ich jetzt den befehl sende, dass netcat an dem port lauschen soll, bleibt das programm einfach stehen. also es stürzt nicht ab, aber es führ auch keine weiteren schritte aus.

    Ich hab jetzt mal den code und die ausgabe hinzugefügt. also wenn ich dein code richtig verstehe, speichert er im readfromprocess die ausgabe als char. kann es sein, dass das probleme bereit, wenn netcat quasi wartet?

    #include <iostream>
    #include <string>
    #include "myConsole.h"

    using namespace std;

    int main()
    {
    myConsole mc;
    mc.doCommand("cd c:\\netcat");

    Sleep(5000);
    string str;
    str = mc.readFromProcess();

    cout << str;
    cout << "\n\n Testausgabe 1\n";

    mc.doCommand("nc -L -v -p 9999");

    Sleep(1000);
    str = mc.readFromProcess();
    cout << str;
    cout << "\n\n Testausgabe 2\n";

    Sleep(1000);
    str = mc.readFromProcess();
    cout << str;
    cout << "\nTestausgabe 3";

    cin.get();
    }

    http://desmond.imageshack.us/Himg705/scaled.php?server=705&filename=ausgabeg.jpg&res=landing

    (ach wenn man netcat manuell schließt, wird das programm weiter ausgeführt und testausgabe 3 ausgegeben.)



  • Belli schrieb:

    [...]

    Edit:
    Nachteil bei dieser threadlosen Lösung ist, wenn der gestartet Prozess nichts mehr schreibt, bleibt das Programm in readFromProcess hängen.

    Ja, in der Methode readFromProcess wird gewartet, bis irgendwas vom gestarteten Prozess geschrieben wird, was hier auch gelesen werden kann. Gelesen wird mittels ReadFile, das ist eine blockierende Funktion, die erst zurückkehrt, wenn es auch Daten zu lesen gibt.
    D.h., wenn netcat nichts mehr schreibt, gibt es für Dein Programm nichts mehr zu lesen und zu verarbeiten.



  • Werfe netcat in die Tonne und verwende die Socket API. Glaube mir: die Mühe ist es Wert. Netcat macht wirklich nicht viel. Anstatt Dich zu wundern, wann welche Pipe wie puffert und wie Du das verhindern kannst und auch noch wie Du von netcat gescheit über Fehler benachrichtigt wirst hast Du die Sachen in halber Zeit mit Sockets programmiert.


Anmelden zum Antworten