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

There is a Win32 utility called RAdmin (Remote Administration) which forwards the mouse/keyboard and/or screen to another PC over Ethernet. It's cool for keeping an eye on a PC running a test stand. But I don't like the idea of someone peeping into my desktop. Let them come see the regular way. RAdmin uses by default, I believe, port 1149.

Who might know of a script one can run which will detect when one's PC is forwarding its screen to an Ethernet Peeping Tom...be they nosy boss or whomever?

Lacking one ready made, how might I get started to write one? In short, how do I monitor 127.0.0.1:1149 or whichever for outgoing screen traffic?

Replies are listed 'Best First'.
Re: RAdmin detector for Win32
by pg (Canon) on Aug 29, 2005 at 02:08 UTC

    The default port for RAdmin is 4899. 127.0.0.1 is sort of not precise. You actually don't want to monitor localhost, but your address on the network.

    Easy ways include: 1) to have a script that runs netstat periodically: netstat -a 10 etc. You can do it through open2, so your script can alert you when centain port is connected. 2) run firewall on your PC (some company does not allow employee to run firewall on their PC, you have to check this first)

    A more complex (might be better) way is to do some pcap programing. But this might be over-engneered, as most likely netstat should be good enough in your case.

Re: RAdmin detector for Win32
by anthski (Scribe) on Aug 29, 2005 at 06:19 UTC
    As suggested by pg, I think the easiest way would be to simply run a script which parsed the output of netstat.

    Something like

    #!C:\perl\bin\perl.exe my $netstat = "C:\\WINDOWS\\System32\\netstat.exe"; my $RAdminPort = "4899"; open(NETSTAT, "$netstat -an -p tcp|") or die "Couldn't run netstat - $ +!\n"; while(<NETSTAT>) { next unless $_ =~ /TCP/; my $line = $_; $line =~ s/\s+//; my ($protocol, $local, $remote, $status) = split(/\s+/, $line, 4); my ($localAddress, $localPort) = split(/:/, $local); if (($localPort eq $RAdminPort) && ($status eq "ESTABLISHED")) { print "Discovered connection to RAdmin from $remote\n"; # Do something here....... } } close(NETSTAT);

    should do the trick, if you run it as a scheduled task every 10 minutes (or however often). You could also write this into a loop which slept for 10 minutes and then opened netstat, etc and save yourself from running it as a task at a defined period, etc.

Re: RAdmin detector for Win32
by puploki (Hermit) on Aug 29, 2005 at 11:03 UTC

    I agree with all the other replies to this - all valid ways of using Perl to check for this open port, but...

    Why are you so concerned about RAdmin in particular? I know from experience that there are thousands of programs around that will quite happily drop a screen capture/keylogger on your machine. Of course, these all run on a myriad of different ports - not to mention the fact that if I wanted, I could change RAdmin's listening port and therefore circumvent your checks.

    The other big killer on an exploited Windows box (much like *NIX) is not to trust any console tools - most backdoor writers these days are savvy enough to hide their processes by running a kernel layer filter. These are most commonly used to hide themselves from task manager, but I wouldn't put it past them to hide their network ports either.

    It's not that any of these suggestions are wrong in the Perl sense, and forgive me if I'm preaching to a learned monk, but it might just lull you into a false sense of security. A good software based firewall (hell, even XP SP2's inbuilt one) are going to cover most of the bases in this area.

      You are correct, of course. But RAdmin is the tool which I know is employed ubiquitously in a certain location. It is installed on all PCs there. It's useful enough for tracking PCs running equipment, as I said. I use it myself.

      But I suspect it's used for more than that. In fact, I'm quite sure.

      In one sense, I don't mind so much that folks may look over my shoulder. It's just terribly impolite to sneek about doing it. Folks are welcome to view my activities all day long. I've nothing to hide. I just think it better they do so in person. Who would not agree that to be invisible while gawking is just plain rude.

      In short, I'm not so concerned as to be paranoid. I don't want to counter it. I just want to know when its happening. A simple matter of courtesy, is all.

      Thanks to all

Re: RAdmin detector for Win32
by aplonis (Pilgrim) on Aug 30, 2005 at 18:20 UTC

    One last question, since I'm not so much a Win32 guy...

    Does NETSTAT for Win32 create any outbound Ethernet traffic? Or does it do its thing entirely on its own side of the port?

    Put another way, will running NETSTAT in a loop raise alarms on the network and bring down the lowering brow of IT SysAdmin types?

      netstat wont create any outbound ethernet traffic. As explained nicely in RFC 1147, netstat is...

      ...a program that accesses network related data structures within the kernel, then provides an ASCII format at the terminal. Netstat can provide reports on the routing table, TCP connections, TCP and UDP "listens," and protocol memory management

      So running netstat in a loop wont bring your local sysadmin running for the reason you cite. Obviously, running anything in a loop without care may cause other problems.

      cheers,
      Anth

Re: RAdmin detector for Win32
by aplonis (Pilgrim) on Aug 30, 2005 at 20:01 UTC

    Okay, for what it's worth, here's my version. It does seem to work well enough:

    #!C:\perl\bin\perl.exe my $netstat = "C:\\WINNT\\System32\\netstat.exe"; sub clear_screen { my $cmd; if ($^O =~ /win32/i) {$cmd = 'cls'} else {$cmd = 'clear'} system($cmd); } sub ferret { my ($line, @ports) = @_; my ($protocol, $local, $other, $status) = split(/\s+/, $line, 4); my ($local_addr, $local_port) = split(/:/, $local); my ($other_addr, $other_port) = split(/:/, $other); my @scan; foreach (@ports) { if ($local_port =~ /$_/){ push @scan, "$local_port -> $other_addr" if $status =~ /ESTABLISHED/; push @scan, "$local_port listening..." if $status =~ /LISTENING/; push @scan, "$local_port waiting..." if $status =~ /TIME_WAIT/; } } return @scan; } # Scan a range of ports, sub scan_range { my $range = shift; my @ports; foreach (@_) {push @ports, ($_-$range .. $_+$range)}; open(NETSTAT, "$netstat -a -p tcp|") or die "Oops! Cannot run netstat: $! \n"; my $report; while(<NETSTAT>) { next unless $_ =~ /TCP/; $_ =~ s/^\s+//; $report .= join "\n", ferret($_, @ports); } close(NETSTAT); $report = "Ports idle..." unless $report; clear_screen(); return "$report\n"; } # Repeatedlt scan certain ports and their immediate neighbors. my @ports = (4899, 8080); # Win32 RAdmin, XML-RPC. my $range = 5; # How many neigbhbors to either side. my $seconds = 60; # How long to wait between scans. my $minutes = 30; # How long to keep re-scaning. for (1 .. int($minutes / $seconds * 60)) { print "Scan $_ ", scan_range($range, @ports); sleep $seconds; }
Re: RAdmin detector for Win32
by kerpau (Novice) on Aug 29, 2005 at 22:14 UTC
    Another bit of info... On Windows XP you could use netstat -b to get the name of the executable that has the connection open. Of course, they could rename the executable to circumvent that as well. But while we're talking about netstat...
Re: RAdmin detector for Win32
by aplonis (Pilgrim) on Sep 08, 2005 at 19:07 UTC

    As promised, here is my version. I made it to scan any port or ports, and their neighbors, however may be desired.

    It sits quitely until it sees a connection. Then it pops up a Tk window.

    Thanks to all.

    #!C:\perl\bin\perl.exe # Note: run under wperl.exe for no DOS window. use Tk; use strict; use warnings; # Repeatedly scan certain ports and their immediate neighbors. my @ports = (4899, 8080); # Win32 RAdmin, XML-RPC. my $range = 5; # How many neigbhbors ports. my $seconds = 30; # How long to wait between scans. my $minutes = 60; # How long to keep re-scaning. my %mw_hash; my $netstat = "C:\\WINNT\\System32\\netstat.exe"; sub clear_screen { my $cmd; if ($^O =~ /win32/i) {$cmd = 'cls'} else {$cmd = 'clear'} system($cmd); } sub ferret { my ($line, @ports) = @_; my ($protocol, $local, $other, $status) = split(/\s+/, $line, 4); my ($local_addr, $local_port) = split(/:/, $local); my ($other_addr, $other_port) = split(/:/, $other); my @scan; foreach (@ports) { if ($local_port =~ /$_/){ if ($status =~ /ESTABLISHED/) { push @scan, "$local_port -> $other_addr\n"; start_MainLoop($local_port,$other,'okay') unless Tk::Exists($mw_hash{$local_port}) } else { quit_one_MainLoop($mw_hash{$local_port}) } push @scan, "$local_port listening...\n" if $status =~ /LISTENING/; push @scan, "$local_port waiting...\n" if $status =~ /TIME_WAIT/; } } return @scan; } # Scan a range of ports, sub scan_range { my $range = shift; my @ports; foreach (@_) {push @ports, ($_-$range .. $_+$range)}; open(NETSTAT, "$netstat -a -p tcp|") or die "Oops! Cannot run netstat: $! \n"; my $report; while(<NETSTAT>) { next unless $_ =~ /TCP/; $_ =~ s/^\s+//; $report .= join "\n", ferret($_, @ports); } close(NETSTAT); $report = "Ports idle...\n" unless $report; clear_screen(); return "$report\n"; } # Pop up a Tk window for each ESTABLISHED socket. sub start_MainLoop { my ($local_port, $msg_txt, $button_txt ) = @_; $mw_hash{$local_port} = MainWindow->new( -title => 'Periscope' ); $mw_hash{$local_port}->Label( -text => " $msg_txt ", -justify => 'left', -font => 'courier', )->pack( -side => 'top', -expand => 1, -fill => 'x' ); $mw_hash{$local_port}->Button( -width => (length($button_txt) + 2), -relief => 'raised', -background => 'blue', -activebackground => 'green', -command => sub { quit_one_MainLoop( $mw_hash{$local_port} ) }, -text => $button_txt, )->pack( -side => 'left', -expand => 1, -fill => 'x' ); $mw_hash{$local_port}->Button( -width => (length($button_txt) + 2), -relief => 'raised', -background => 'orange', -activebackground => 'red', -command => \&quit_all_MainLoops, -text => 'Exit All', )->pack( -side => 'left', -expand => 1, -fill => 'x' ); MainLoop; } # Close down the Perl/Tk GUI sub quit_one_MainLoop { my $mw = shift; $mw->destroy() if Tk::Exists($mw) } sub quit_all_MainLoops { foreach (keys %mw_hash) { quit_one_MainLoop($mw_hash{$_}) } } my $scans = int($minutes / $seconds * 60); for (1 .. $scans) { print "Scan $_ of $scans \n", scan_range($range, @ports); sleep $seconds; }