netcat mit c++ bedienen



  • Einen schönen guten Morgen wünsche ich,
    ich habe eine Frage (Sie ist vllt auch ohne Netcat kenntnise beantwortbar):
    Ich möchte mittels c++ Script netcat starten und eine Verbindung aufbauen (Dies funktioniert auch soweit):

    #include <iomanip.h>
    #include <windows.h>
    int main()
    {
    
    system("nc -v -L -p 8888");
    
    cin.get();return(0);    
    }
    

    Ich starte in einem zweiten Fenster Netcat und baue eine Verbindung zu dem Port 8888 auf. Nun kann man Text in eine der beiden Konsolen eingeben und dieser wird zum jeweils anderem gesendet. Soweit so gut.
    Nun soll das C++ Programm aber einen String versenden, also ich möchte nicht selbst was in die Konsole eintippen, sondern C++ soll dies für mich erledigen.

    Wenn ich nach dem Verbindungsaufbau

    cout << "TEXT";
    

    oder

    system("TEXT");
    

    oder

    system("echo TEXT");
    

    verwende passiert nichts. Wisst ihr wie man das hinbekommen kann? Vielen Dank im Voraus 🙂



  • echo foobar | nc -v -L -p 8888



  • Vielen Dank für die schnelle Antwort. Es funktioniert jetzt, dass beim erstellen der Verbindung das Wort foolbar übertragen wird.

    Ist es auch möglich, dass weitere texte übertragen werden? Also nicht nur beim erstellen der verbindung?



  • Dafür muss du den Standard-Eingabestrom des Programms (Das ist jetzt dein Stichwort für Google) umleiten.



  • Mit der folgenden Klasse kannst Du eine Konsole erstellen und steuern:
    Hilfsklasse pipe:

    #ifndef PIPEH
    #define PIPEH
    
    #include <windows.h>
    
    class pipe
    {
    	public:
    		enum pipeEnde {READ, WRITE};
    
    		pipe();
    		~pipe();
    
    		HANDLE GetPipeHandle(pipeEnde end);
    
    		void MakeInheritable(pipeEnde end);
    		void ClosePipeHandle(pipeEnde end);
    
    	private:
    
    		HANDLE readEnd, writeEnd;	
    
    		void MakeInheritable(HANDLE *h, bool inheritable);
    
    		//dont copy || assign
    		pipe(const pipe &);
    		pipe& operator=(const pipe &);
    };
    
    #endif
    
    #include "pipe.h"
    
    //Konstruktor
    pipe::pipe()
    {
    	CreatePipe(&readEnd, &writeEnd, NULL, 0);
    }
    
    //Destruktor
    pipe::~pipe()
    {
    	ClosePipeHandle(READ);
    	ClosePipeHandle(WRITE);
    }
    
    //public
    void pipe::ClosePipeHandle(pipeEnde end)
    {
    	switch(end)
    	{
    		case READ:
    				if(readEnd)
    				{
    					CloseHandle(readEnd);
    					readEnd = 0;
    				}
    				break;
    		case WRITE:
    				if(writeEnd)
    				{
    					CloseHandle(writeEnd);
    					writeEnd = 0;
    				}
    				break;
    	}
    }
    
    HANDLE pipe::GetPipeHandle(pipeEnde end)
    {
    	switch(end)
    	{
    		case READ:  return readEnd;
    		case WRITE: return writeEnd;
    	}
    
    	return NULL;
    }
    
    void pipe::MakeInheritable(pipeEnde end)
    {
    	switch(end)
    	{
    		case READ:
    				MakeInheritable(&readEnd, true); 
    				MakeInheritable(&writeEnd, false);
    				break;
    		case WRITE:
    				MakeInheritable(&readEnd, false); 
    				MakeInheritable(&writeEnd, true);
    				break;
    	}
    }
    
    //private
    void pipe::MakeInheritable(HANDLE *h, bool inheritable)
    {
    	if(!h)
    		return;
    
    	HANDLE proc = GetCurrentProcess();
    
    	DuplicateHandle(proc, *h, proc, h, 0, inheritable, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);
    }
    

    die Klasse myConsole:

    #ifndef MYCONSOLEH
    #define MYCONSOLEH
    
    #include <string>
    #include "pipe.h"
    
    class myConsole
    {
    	public:
    		myConsole();
    		~myConsole();
    		void doCommand(std::string command);
    
    	private:
    
    		pipe writePipe;
    };
    
    #endif
    
    #include <iostream>
    #include "myConsole.h"
    
    //public
    
    void myConsole::doCommand(std::string command)
    {	
    	DWORD ignore;
    
    	command.append("\n");
    	bool wf = WriteFile(writePipe.GetPipeHandle(pipe::WRITE), command.c_str(), command.size(), &ignore, 0);
    }
    
    myConsole::~myConsole()
    {
    	doCommand("exit\n");
    }
    
    myConsole::myConsole()
    {
       PROCESS_INFORMATION pi;
       STARTUPINFO si;
    
    	writePipe.MakeInheritable(pipe::READ);
    
       // Set up the start up info struct.
       ZeroMemory(&si,sizeof(STARTUPINFO));
       si.cb = sizeof(STARTUPINFO);
       si.dwFlags = STARTF_USESTDHANDLES;
       si.hStdInput = writePipe.GetPipeHandle(pipe::READ);
       si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
       si.hStdError = GetStdHandle(STD_OUTPUT_HANDLE);
    
       CreateProcess(0, "cmd.exe", NULL, NULL, TRUE, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi);
    	writePipe.ClosePipeHandle(pipe::READ);
    
       CloseHandle(pi.hThread);
       CloseHandle(pi.hProcess);
    }
    

    ein Testprogramm:

    #include "myConsole.h"
    #include <iostream>
    
    using namespace std;
    
    int main()
    {
    	myConsole mc;
    
    	mc.doCommand("dir");
    	Sleep(2000);
    
    	mc.doCommand("cd ..");
    	Sleep(2000);
    
    	mc.doCommand("dir /W");
    	Sleep(2000);
    }
    


  • Okay hab ich gemacht 😃 scheint mit rdbuf() zu funktionieren? das lese ich mir jetzt genauer durch.

    edit: oh da hat noch jmd was gepostet^^ vielen dank dafür. das gucke ich mir auch eben an 🙂



  • Das ist Windowscode ...



  • ja, und? Ist im Eingangsposting doch auch schon Windows-Code.



  • @314159265358979 okay ich hab erfahren, dass man die ausgabe, in z.B. eine beliebige .txt datei, umleiten kann. aber wohin müsste ich nun meine ausgabe umleiten? die ausgabe soll ja eigentlich direkt in die konsole die beim ausführen des programms geöffnet wird.

    @Ethon: was ist denn schlimm an windowscode?^^

    @Belli: hm, das scheint mir ja relativ viel aufwand zu sein. ich kenne mich bisher nur in den ganzen grundlagen aus. aber bist du sicher, dass das alles sein muss um mein problem zu lösen?



  • Die Klassen habe ich Dir doch schon geliefert, die kannst Du erst mal so nehmen. Dein 'Aufwand' besteht dann nur noch darin, im og Testprogramm die richtigen Befehle an doCommand() zu übergeben.
    zB:
    doCommand("echo foobar | nc -v -L -p 8888");

    etc.

    Die Klassen erledigen für Dich das von PI erwähnte umlenken des Standard-Eingabe-Streams.



  • okay, vielen dank! ich habe verstanden, dass ich quasi nurnoch den letzten code anpassen müsste. ich dachte nur dass es ein problem ist was mit einem befehl oder so ähnlich gelöst werden könnte.

    Ich habe keine erfahrung damit selbst klassen anzulegen. müsste ich für jeden code eine datei erstellen und nacheinander ausführen (wenn ja ist der dateiname entscheidend?) oder alles in eins?



  • Du könntest das ganze auch mit WIN Sock machen und ganz auf Netcar 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. )



  • Ach mist, zu spät geantwortet aber ich glaube du solltest dir diesen Link mal anschauen:

    http://www.cpp-tutor.de/cpp/le09/klassen.html



  • jasdefer schrieb:

    Ich habe keine erfahrung damit selbst klassen anzulegen. müsste ich für jeden code eine datei erstellen und nacheinander ausführen (wenn ja ist der dateiname entscheidend?) oder alles in eins?

    Üb mal. Du legst die Dateien an, pipe.h, pipe.cpp, myConsole.h, myConsole.cpp und test.cpp wie oben.
    Dann navigierst Du mit Deiner Visual Studio - Eingabeaufforderung in das Verzeichnis und gibst ein:
    cl /EHsc test.cpp pipe.cpp myconsole.cpp

    dann sollte das fertige Programm test.exe entstehen.
    Wenn Du damit Probleme haben solltest, solltest Du evtl. erst noch ein paar Grundlagen lernen, bevor Du Dich mit weiterführenden Problemen beschäftigst.



  • Belli schrieb:

    ja, und? Ist im Eingangsposting doch auch schon Windows-Code.

    Naja, bis auf das <windows.h> nicht und das habe ich übersehen. 😉



  • @Belli ist dies auch mit anderen compilern möglich? ich benutze dev-c++ und nicht visual studio.

    @Held vom MSDN !: ist es besser es nicht mit netcat zu machen? soweit funktioniert mit netcat eigentlich alles recht gut



  • @Belli. yeah 😃 es hat geklappt. habs hinbekommen. VIELEN DANK EUCH ALLEN



  • jasdefer schrieb:

    @Belli ist dies auch mit anderen compilern möglich? ich benutze dev-c++ und nicht visual studio.

    Klar, funktioniert ein wenig anders in der Aufrufsyntax, aber das Prinzip ist identisch.
    Wie ich sehe, hast Dus ja auch schon geschafft 🙂
    @Ethon:
    Gerade wegen des windows.h habe ich diesen Entwurf gepostet, ohne explizit darauf hinzuweisen, dass es eine Windows-Lösung ist. Ich hatte einen guten Teil des Codes hier rumfliegen, weil ich vor ein paar Tagen einen Vorschlag für eine Klasse im Konsolenforum gepostet hatte, wo es darum ging, die Programme zu starten und die Ausgabe abzufangen.



  • ja man musste ein projekt erstellen und dort dann klassen hinzufügen und dein code da reinkopieren.

    mein mainprogramm sieht jetzt so aus

    #include <cstdlib>
    #include <iostream>
    #include "pipe.h"
    #include "myconsole.h"
    
    using namespace std;
    
    int main(int argc, char *argv[])
    {
    
        myConsole mc;
    
        mc.doCommand("d:");
        mc.doCommand("cd netcat");
        mc.doCommand("nc -L -v -p 9999>E:\\Desktop\\testing\\PROJEKT\\data.txt");  
    }
    

    er soll auf eine verbindung warten und die eingehenden daten in eine datei speichern. wenn ich jetzt mit einem zweitem fenster per netcat eine verbindung dazu aufbaue klappt auch alles wunderbar. nur wird in dem jetzt manuell von mir geöffnetem fenster das wort exit ausgegeben. warum das?



  • Ach und noch eine Frage, wie funktioniert jetzt die syntax mit doCommand wenn ich variablen senden möchte?
    es scheint ja so zusein, dass dahinter nur n string erwartet wird (laut der myconsole.h datei) oder kann ich da jetzt einfach n zweiten befehl hinzufügen wo dann ein zB int erwartet wird. wenn ja wie(syntax mäßig)?^^


Anmelden zum Antworten